Separate file utilities from utils.cc

Reduce the dependencies from utils.cc to arch/ subdirectories, etc.

Bug: 22322814
Test: make test-art-host
Change-Id: I4decd15ff4ec460735bfb58cebb1c6a1bf32b68f
diff --git a/cmdline/cmdline.h b/cmdline/cmdline.h
index c5d3a6b..2929f36 100644
--- a/cmdline/cmdline.h
+++ b/cmdline/cmdline.h
@@ -26,6 +26,7 @@
 
 #include "android-base/stringprintf.h"
 
+#include "base/file_utils.h"
 #include "base/logging.h"
 #include "base/stringpiece.h"
 #include "noop_compiler_callbacks.h"
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index affe639..1cd9142 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -43,6 +43,7 @@
 #include "art_method-inl.h"
 #include "base/callee_save_type.h"
 #include "base/dumpable.h"
+#include "base/file_utils.h"
 #include "base/macros.h"
 #include "base/scoped_flock.h"
 #include "base/stl_util.h"
diff --git a/dex2oat/dex2oat_image_test.cc b/dex2oat/dex2oat_image_test.cc
index 0a50681..a02fbf8 100644
--- a/dex2oat/dex2oat_image_test.cc
+++ b/dex2oat/dex2oat_image_test.cc
@@ -24,6 +24,7 @@
 
 #include "common_runtime_test.h"
 
+#include "base/file_utils.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/unix_file/fd_file.h"
diff --git a/dex2oat/linker/elf_writer_test.cc b/dex2oat/linker/elf_writer_test.cc
index 9f8ed77..8427e7b 100644
--- a/dex2oat/linker/elf_writer_test.cc
+++ b/dex2oat/linker/elf_writer_test.cc
@@ -16,6 +16,7 @@
 
 #include "elf_file.h"
 
+#include "base/file_utils.h"
 #include "base/unix_file/fd_file.h"
 #include "common_compiler_test.h"
 #include "elf_file.h"
diff --git a/dex2oat/linker/image_test.h b/dex2oat/linker/image_test.h
index dc570da..d3d42b9 100644
--- a/dex2oat/linker/image_test.h
+++ b/dex2oat/linker/image_test.h
@@ -26,6 +26,7 @@
 #include "android-base/stringprintf.h"
 
 #include "art_method-inl.h"
+#include "base/file_utils.h"
 #include "base/unix_file/fd_file.h"
 #include "class_linker-inl.h"
 #include "common_compiler_test.h"
diff --git a/dexlayout/dexdiag_test.cc b/dexlayout/dexdiag_test.cc
index 6fcd6ff..9927576 100644
--- a/dexlayout/dexdiag_test.cc
+++ b/dexlayout/dexdiag_test.cc
@@ -19,6 +19,7 @@
 
 #include "common_runtime_test.h"
 
+#include "base/file_utils.h"
 #include "exec_utils.h"
 #include "oat_file.h"
 #include "os.h"
diff --git a/dexoptanalyzer/dexoptanalyzer.cc b/dexoptanalyzer/dexoptanalyzer.cc
index 08d38d5..b16bbb6 100644
--- a/dexoptanalyzer/dexoptanalyzer.cc
+++ b/dexoptanalyzer/dexoptanalyzer.cc
@@ -18,6 +18,7 @@
 
 #include "android-base/stringprintf.h"
 #include "android-base/strings.h"
+#include "base/file_utils.h"
 #include "compiler_filter.h"
 #include "dex_file.h"
 #include "noop_compiler_callbacks.h"
diff --git a/oatdump/oatdump_test.h b/oatdump/oatdump_test.h
index 52fe973..d0f05d9 100644
--- a/oatdump/oatdump_test.h
+++ b/oatdump/oatdump_test.h
@@ -24,6 +24,7 @@
 #include "android-base/strings.h"
 
 #include "arch/instruction_set.h"
+#include "base/file_utils.h"
 #include "base/unix_file/fd_file.h"
 #include "common_runtime_test.h"
 #include "exec_utils.h"
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 3258aae..4c4ea58 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -35,6 +35,7 @@
         "base/arena_bit_vector.cc",
         "base/bit_vector.cc",
         "base/file_magic.cc",
+        "base/file_utils.cc",
         "base/hex_dump.cc",
         "base/logging.cc",
         "base/mutex.cc",
diff --git a/runtime/base/file_utils.cc b/runtime/base/file_utils.cc
new file mode 100644
index 0000000..323a065
--- /dev/null
+++ b/runtime/base/file_utils.cc
@@ -0,0 +1,356 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "file_utils.h"
+
+#include <inttypes.h>
+#include <pthread.h>
+#include <sys/mman.h>  // For madvise
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+// We need dladdr.
+#ifndef __APPLE__
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#define DEFINED_GNU_SOURCE
+#endif
+#include <dlfcn.h>
+#include <libgen.h>
+#ifdef DEFINED_GNU_SOURCE
+#undef _GNU_SOURCE
+#undef DEFINED_GNU_SOURCE
+#endif
+#endif
+
+
+#include <memory>
+
+#include "android-base/stringprintf.h"
+#include "android-base/strings.h"
+
+#include "base/stl_util.h"
+#include "base/unix_file/fd_file.h"
+#include "dex_file-inl.h"
+#include "dex_file_loader.h"
+#include "dex_instruction.h"
+#include "oat_quick_method_header.h"
+#include "os.h"
+#include "scoped_thread_state_change-inl.h"
+#include "utf-inl.h"
+
+#if defined(__APPLE__)
+#include <crt_externs.h>
+#include <sys/syscall.h>
+#include "AvailabilityMacros.h"  // For MAC_OS_X_VERSION_MAX_ALLOWED
+#endif
+
+#if defined(__linux__)
+#include <linux/unistd.h>
+#endif
+
+namespace art {
+
+using android::base::StringAppendF;
+using android::base::StringPrintf;
+
+bool ReadFileToString(const std::string& file_name, std::string* result) {
+  File file(file_name, O_RDONLY, false);
+  if (!file.IsOpened()) {
+    return false;
+  }
+
+  std::vector<char> buf(8 * KB);
+  while (true) {
+    int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[0], buf.size()));
+    if (n == -1) {
+      return false;
+    }
+    if (n == 0) {
+      return true;
+    }
+    result->append(&buf[0], n);
+  }
+}
+
+bool PrintFileToLog(const std::string& file_name, LogSeverity level) {
+  File file(file_name, O_RDONLY, false);
+  if (!file.IsOpened()) {
+    return false;
+  }
+
+  constexpr size_t kBufSize = 256;  // Small buffer. Avoid stack overflow and stack size warnings.
+  char buf[kBufSize + 1];           // +1 for terminator.
+  size_t filled_to = 0;
+  while (true) {
+    DCHECK_LT(filled_to, kBufSize);
+    int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[filled_to], kBufSize - filled_to));
+    if (n <= 0) {
+      // Print the rest of the buffer, if it exists.
+      if (filled_to > 0) {
+        buf[filled_to] = 0;
+        LOG(level) << buf;
+      }
+      return n == 0;
+    }
+    // Scan for '\n'.
+    size_t i = filled_to;
+    bool found_newline = false;
+    for (; i < filled_to + n; ++i) {
+      if (buf[i] == '\n') {
+        // Found a line break, that's something to print now.
+        buf[i] = 0;
+        LOG(level) << buf;
+        // Copy the rest to the front.
+        if (i + 1 < filled_to + n) {
+          memmove(&buf[0], &buf[i + 1], filled_to + n - i - 1);
+          filled_to = filled_to + n - i - 1;
+        } else {
+          filled_to = 0;
+        }
+        found_newline = true;
+        break;
+      }
+    }
+    if (found_newline) {
+      continue;
+    } else {
+      filled_to += n;
+      // Check if we must flush now.
+      if (filled_to == kBufSize) {
+        buf[kBufSize] = 0;
+        LOG(level) << buf;
+        filled_to = 0;
+      }
+    }
+  }
+}
+
+std::string GetAndroidRootSafe(std::string* error_msg) {
+  // Prefer ANDROID_ROOT if it's set.
+  const char* android_dir = getenv("ANDROID_ROOT");
+  if (android_dir != nullptr) {
+    if (!OS::DirectoryExists(android_dir)) {
+      *error_msg = StringPrintf("Failed to find ANDROID_ROOT directory %s", android_dir);
+      return "";
+    }
+    return android_dir;
+  }
+
+  // Check where libart is from, and derive from there. Only do this for non-Mac.
+#ifndef __APPLE__
+  {
+    Dl_info info;
+    if (dladdr(reinterpret_cast<const void*>(&GetAndroidRootSafe), /* out */ &info) != 0) {
+      // Make a duplicate of the fname so dirname can modify it.
+      UniqueCPtr<char> fname(strdup(info.dli_fname));
+
+      char* dir1 = dirname(fname.get());  // This is the lib directory.
+      char* dir2 = dirname(dir1);         // This is the "system" directory.
+      if (OS::DirectoryExists(dir2)) {
+        std::string tmp = dir2;  // Make a copy here so that fname can be released.
+        return tmp;
+      }
+    }
+  }
+#endif
+
+  // Try "/system".
+  if (!OS::DirectoryExists("/system")) {
+    *error_msg = "Failed to find ANDROID_ROOT directory /system";
+    return "";
+  }
+  return "/system";
+}
+
+std::string GetAndroidRoot() {
+  std::string error_msg;
+  std::string ret = GetAndroidRootSafe(&error_msg);
+  if (ret.empty()) {
+    LOG(FATAL) << error_msg;
+    UNREACHABLE();
+  }
+  return ret;
+}
+
+
+static const char* GetAndroidDirSafe(const char* env_var,
+                                     const char* default_dir,
+                                     std::string* error_msg) {
+  const char* android_dir = getenv(env_var);
+  if (android_dir == nullptr) {
+    if (OS::DirectoryExists(default_dir)) {
+      android_dir = default_dir;
+    } else {
+      *error_msg = StringPrintf("%s not set and %s does not exist", env_var, default_dir);
+      return nullptr;
+    }
+  }
+  if (!OS::DirectoryExists(android_dir)) {
+    *error_msg = StringPrintf("Failed to find %s directory %s", env_var, android_dir);
+    return nullptr;
+  }
+  return android_dir;
+}
+
+static const char* GetAndroidDir(const char* env_var, const char* default_dir) {
+  std::string error_msg;
+  const char* dir = GetAndroidDirSafe(env_var, default_dir, &error_msg);
+  if (dir != nullptr) {
+    return dir;
+  } else {
+    LOG(FATAL) << error_msg;
+    return nullptr;
+  }
+}
+
+const char* GetAndroidData() {
+  return GetAndroidDir("ANDROID_DATA", "/data");
+}
+
+const char* GetAndroidDataSafe(std::string* error_msg) {
+  return GetAndroidDirSafe("ANDROID_DATA", "/data", error_msg);
+}
+
+std::string GetDefaultBootImageLocation(std::string* error_msg) {
+  std::string android_root = GetAndroidRootSafe(error_msg);
+  if (android_root.empty()) {
+    return "";
+  }
+  return StringPrintf("%s/framework/boot.art", android_root.c_str());
+}
+
+void GetDalvikCache(const char* subdir, const bool create_if_absent, std::string* dalvik_cache,
+                    bool* have_android_data, bool* dalvik_cache_exists, bool* is_global_cache) {
+  CHECK(subdir != nullptr);
+  std::string error_msg;
+  const char* android_data = GetAndroidDataSafe(&error_msg);
+  if (android_data == nullptr) {
+    *have_android_data = false;
+    *dalvik_cache_exists = false;
+    *is_global_cache = false;
+    return;
+  } else {
+    *have_android_data = true;
+  }
+  const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data));
+  *dalvik_cache = dalvik_cache_root + subdir;
+  *dalvik_cache_exists = OS::DirectoryExists(dalvik_cache->c_str());
+  *is_global_cache = strcmp(android_data, "/data") == 0;
+  if (create_if_absent && !*dalvik_cache_exists && !*is_global_cache) {
+    // Don't create the system's /data/dalvik-cache/... because it needs special permissions.
+    *dalvik_cache_exists = ((mkdir(dalvik_cache_root.c_str(), 0700) == 0 || errno == EEXIST) &&
+                            (mkdir(dalvik_cache->c_str(), 0700) == 0 || errno == EEXIST));
+  }
+}
+
+std::string GetDalvikCache(const char* subdir) {
+  CHECK(subdir != nullptr);
+  const char* android_data = GetAndroidData();
+  const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data));
+  const std::string dalvik_cache = dalvik_cache_root + subdir;
+  if (!OS::DirectoryExists(dalvik_cache.c_str())) {
+    // TODO: Check callers. Traditional behavior is to not abort.
+    return "";
+  }
+  return dalvik_cache;
+}
+
+bool GetDalvikCacheFilename(const char* location, const char* cache_location,
+                            std::string* filename, std::string* error_msg) {
+  if (location[0] != '/') {
+    *error_msg = StringPrintf("Expected path in location to be absolute: %s", location);
+    return false;
+  }
+  std::string cache_file(&location[1]);  // skip leading slash
+  if (!android::base::EndsWith(location, ".dex") &&
+      !android::base::EndsWith(location, ".art") &&
+      !android::base::EndsWith(location, ".oat")) {
+    cache_file += "/";
+    cache_file += DexFileLoader::kClassesDex;
+  }
+  std::replace(cache_file.begin(), cache_file.end(), '/', '@');
+  *filename = StringPrintf("%s/%s", cache_location, cache_file.c_str());
+  return true;
+}
+
+std::string GetVdexFilename(const std::string& oat_location) {
+  return ReplaceFileExtension(oat_location, "vdex");
+}
+
+static void InsertIsaDirectory(const InstructionSet isa, std::string* filename) {
+  // in = /foo/bar/baz
+  // out = /foo/bar/<isa>/baz
+  size_t pos = filename->rfind('/');
+  CHECK_NE(pos, std::string::npos) << *filename << " " << isa;
+  filename->insert(pos, "/", 1);
+  filename->insert(pos + 1, GetInstructionSetString(isa));
+}
+
+std::string GetSystemImageFilename(const char* location, const InstructionSet isa) {
+  // location = /system/framework/boot.art
+  // filename = /system/framework/<isa>/boot.art
+  std::string filename(location);
+  InsertIsaDirectory(isa, &filename);
+  return filename;
+}
+
+bool FileExists(const std::string& filename) {
+  struct stat buffer;
+  return stat(filename.c_str(), &buffer) == 0;
+}
+
+bool FileExistsAndNotEmpty(const std::string& filename) {
+  struct stat buffer;
+  if (stat(filename.c_str(), &buffer) != 0) {
+    return false;
+  }
+  return buffer.st_size > 0;
+}
+
+std::string ReplaceFileExtension(const std::string& filename, const std::string& new_extension) {
+  const size_t last_ext = filename.find_last_of('.');
+  if (last_ext == std::string::npos) {
+    return filename + "." + new_extension;
+  } else {
+    return filename.substr(0, last_ext + 1) + new_extension;
+  }
+}
+
+int64_t GetFileSizeBytes(const std::string& filename) {
+  struct stat stat_buf;
+  int rc = stat(filename.c_str(), &stat_buf);
+  return rc == 0 ? stat_buf.st_size : -1;
+}
+
+int MadviseLargestPageAlignedRegion(const uint8_t* begin, const uint8_t* end, int advice) {
+  DCHECK_LE(begin, end);
+  begin = AlignUp(begin, kPageSize);
+  end = AlignDown(end, kPageSize);
+  if (begin < end) {
+    int result = madvise(const_cast<uint8_t*>(begin), end - begin, advice);
+    if (result != 0) {
+      PLOG(WARNING) << "madvise failed " << result;
+    }
+    return result;
+  }
+  return 0;
+}
+
+}  // namespace art
diff --git a/runtime/base/file_utils.h b/runtime/base/file_utils.h
new file mode 100644
index 0000000..007f3b4
--- /dev/null
+++ b/runtime/base/file_utils.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef ART_RUNTIME_BASE_FILE_UTILS_H_
+#define ART_RUNTIME_BASE_FILE_UTILS_H_
+
+#include <stdlib.h>
+
+#include <string>
+
+#include "arch/instruction_set.h"
+#include "base/logging.h"
+
+namespace art {
+
+bool ReadFileToString(const std::string& file_name, std::string* result);
+bool PrintFileToLog(const std::string& file_name, LogSeverity level);
+
+// Find $ANDROID_ROOT, /system, or abort.
+std::string GetAndroidRoot();
+// Find $ANDROID_ROOT, /system, or return an empty string.
+std::string GetAndroidRootSafe(std::string* error_msg);
+
+// Find $ANDROID_DATA, /data, or abort.
+const char* GetAndroidData();
+// Find $ANDROID_DATA, /data, or return null.
+const char* GetAndroidDataSafe(std::string* error_msg);
+
+// Returns the default boot image location (ANDROID_ROOT/framework/boot.art).
+// Returns an empty string if ANDROID_ROOT is not set.
+std::string GetDefaultBootImageLocation(std::string* error_msg);
+
+// Returns the dalvik-cache location, with subdir appended. Returns the empty string if the cache
+// could not be found.
+std::string GetDalvikCache(const char* subdir);
+// Return true if we found the dalvik cache and stored it in the dalvik_cache argument.
+// have_android_data will be set to true if we have an ANDROID_DATA that exists,
+// dalvik_cache_exists will be true if there is a dalvik-cache directory that is present.
+// The flag is_global_cache tells whether this cache is /data/dalvik-cache.
+void GetDalvikCache(const char* subdir, bool create_if_absent, std::string* dalvik_cache,
+                    bool* have_android_data, bool* dalvik_cache_exists, bool* is_global_cache);
+
+// Returns the absolute dalvik-cache path for a DexFile or OatFile. The path returned will be
+// rooted at cache_location.
+bool GetDalvikCacheFilename(const char* file_location, const char* cache_location,
+                            std::string* filename, std::string* error_msg);
+
+// Returns the system location for an image
+std::string GetSystemImageFilename(const char* location, InstructionSet isa);
+
+// Returns the vdex filename for the given oat filename.
+std::string GetVdexFilename(const std::string& oat_filename);
+
+// Returns true if the file exists.
+bool FileExists(const std::string& filename);
+bool FileExistsAndNotEmpty(const std::string& filename);
+
+// Returns `filename` with the text after the last occurrence of '.' replaced with
+// `extension`. If `filename` does not contain a period, returns a string containing `filename`,
+// a period, and `new_extension`.
+// Example: ReplaceFileExtension("foo.bar", "abc") == "foo.abc"
+//          ReplaceFileExtension("foo", "abc") == "foo.abc"
+std::string ReplaceFileExtension(const std::string& filename, const std::string& new_extension);
+
+// Return the file size in bytes or -1 if the file does not exists.
+int64_t GetFileSizeBytes(const std::string& filename);
+
+// Madvise the largest page aligned region within begin and end.
+int MadviseLargestPageAlignedRegion(const uint8_t* begin, const uint8_t* end, int advice);
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_BASE_FILE_UTILS_H_
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index 149c33f..f15acf9 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -27,6 +27,7 @@
 #include "android-base/stringprintf.h"
 
 #include "art_field-inl.h"
+#include "base/file_utils.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/stl_util.h"
diff --git a/runtime/dex2oat_environment_test.h b/runtime/dex2oat_environment_test.h
index 57cef3d..5f9b3cf 100644
--- a/runtime/dex2oat_environment_test.h
+++ b/runtime/dex2oat_environment_test.h
@@ -23,6 +23,7 @@
 
 #include <gtest/gtest.h>
 
+#include "base/file_utils.h"
 #include "base/stl_util.h"
 #include "common_runtime_test.h"
 #include "compiler_callbacks.h"
diff --git a/runtime/dex_file_layout.cc b/runtime/dex_file_layout.cc
index 4375d7f..c3fae15 100644
--- a/runtime/dex_file_layout.cc
+++ b/runtime/dex_file_layout.cc
@@ -18,6 +18,7 @@
 
 #include <sys/mman.h>
 
+#include "base/file_utils.h"
 #include "dex_file.h"
 #include "utils.h"
 
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index 4d4d8ff..7beff96 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -18,6 +18,7 @@
 
 #include "art_field-inl.h"
 #include "base/enums.h"
+#include "base/file_utils.h"
 #include "base/histogram-inl.h"
 #include "base/stl_util.h"
 #include "base/systrace.h"
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index 2dc5acc..c6caf4b 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -24,6 +24,7 @@
 
 #include "base/bounded_fifo.h"
 #include "base/enums.h"
+#include "base/file_utils.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/mutex-inl.h"
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 4f54582..9f62666 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -28,6 +28,7 @@
 #include "base/allocator.h"
 #include "base/arena_allocator.h"
 #include "base/dumpable.h"
+#include "base/file_utils.h"
 #include "base/histogram-inl.h"
 #include "base/memory_tool.h"
 #include "base/stl_util.h"
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index f0eada3..74813b4 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -30,6 +30,7 @@
 #include "art_method-inl.h"
 #include "base/callee_save_type.h"
 #include "base/enums.h"
+#include "base/file_utils.h"
 #include "base/macros.h"
 #include "base/scoped_flock.h"
 #include "base/stl_util.h"
diff --git a/runtime/gc/space/image_space_fs.h b/runtime/gc/space/image_space_fs.h
index 5999548..bdb2eda 100644
--- a/runtime/gc/space/image_space_fs.h
+++ b/runtime/gc/space/image_space_fs.h
@@ -22,6 +22,7 @@
 
 #include "android-base/stringprintf.h"
 
+#include "base/file_utils.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/unix_file/fd_file.h"
diff --git a/runtime/gc/verification.cc b/runtime/gc/verification.cc
index beb43df..3cd04a6 100644
--- a/runtime/gc/verification.cc
+++ b/runtime/gc/verification.cc
@@ -20,6 +20,7 @@
 #include <sstream>
 
 #include "art_field-inl.h"
+#include "base/file_utils.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-refvisitor-inl.h"
 
diff --git a/runtime/jit/profile_compilation_info.cc b/runtime/jit/profile_compilation_info.cc
index 19501de..805b9c1 100644
--- a/runtime/jit/profile_compilation_info.cc
+++ b/runtime/jit/profile_compilation_info.cc
@@ -34,6 +34,7 @@
 
 #include "base/arena_allocator.h"
 #include "base/dumpable.h"
+#include "base/file_utils.h"
 #include "base/mutex.h"
 #include "base/scoped_flock.h"
 #include "base/stl_util.h"
diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc
index 743604c..7f68d2f 100644
--- a/runtime/mem_map.cc
+++ b/runtime/mem_map.cc
@@ -34,6 +34,7 @@
 
 #include "base/allocator.h"
 #include "base/bit_utils.h"
+#include "base/file_utils.h"
 #include "base/memory_tool.h"
 #include "globals.h"
 #include "utils.h"
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index 4ab8908..6059b89 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -20,6 +20,7 @@
 
 #include "android-base/stringprintf.h"
 
+#include "base/file_utils.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "class_linker.h"
diff --git a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
index dd98e25..f5057b0 100644
--- a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
+++ b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
@@ -16,6 +16,7 @@
 
 #include "org_apache_harmony_dalvik_ddmc_DdmVmInternal.h"
 
+#include "base/file_utils.h"
 #include "base/logging.h"
 #include "base/mutex.h"
 #include "debugger.h"
diff --git a/runtime/native_stack_dump.cc b/runtime/native_stack_dump.cc
index 7e16357..f166714 100644
--- a/runtime/native_stack_dump.cc
+++ b/runtime/native_stack_dump.cc
@@ -40,6 +40,7 @@
 #include "android-base/stringprintf.h"
 
 #include "arch/instruction_set.h"
+#include "base/file_utils.h"
 #include "base/memory_tool.h"
 #include "base/mutex.h"
 #include "base/unix_file/fd_file.h"
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 1269dca..d64986e 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -38,6 +38,7 @@
 #include "art_method.h"
 #include "base/bit_vector.h"
 #include "base/enums.h"
+#include "base/file_utils.h"
 #include "base/stl_util.h"
 #include "base/systrace.h"
 #include "base/unix_file/fd_file.h"
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index a7fe9b1..fbb312e 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -23,6 +23,7 @@
 #include "android-base/stringprintf.h"
 #include "android-base/strings.h"
 
+#include "base/file_utils.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "class_linker.h"
diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc
index 940195c..ee35d9c 100644
--- a/runtime/oat_file_manager.cc
+++ b/runtime/oat_file_manager.cc
@@ -25,6 +25,7 @@
 
 #include "art_field-inl.h"
 #include "base/bit_vector-inl.h"
+#include "base/file_utils.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "base/systrace.h"
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index 71d7b6c..526f6d1 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -18,6 +18,7 @@
 
 #include <sstream>
 
+#include "base/file_utils.h"
 #include "base/logging.h"
 #include "base/stringpiece.h"
 #include "debugger.h"
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index ec210d0..139de2b 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -60,6 +60,7 @@
 #include "base/arena_allocator.h"
 #include "base/dumpable.h"
 #include "base/enums.h"
+#include "base/file_utils.h"
 #include "base/memory_tool.h"
 #include "base/stl_util.h"
 #include "base/systrace.h"
diff --git a/runtime/runtime_common.cc b/runtime/runtime_common.cc
index 940e461..eb69d91 100644
--- a/runtime/runtime_common.cc
+++ b/runtime/runtime_common.cc
@@ -25,6 +25,7 @@
 
 #include "android-base/stringprintf.h"
 
+#include "base/file_utils.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/mutex.h"
diff --git a/runtime/signal_catcher.cc b/runtime/signal_catcher.cc
index a1f14be..bf5d718 100644
--- a/runtime/signal_catcher.cc
+++ b/runtime/signal_catcher.cc
@@ -34,6 +34,7 @@
 #endif
 
 #include "arch/instruction_set.h"
+#include "base/file_utils.h"
 #include "base/time_utils.h"
 #include "base/unix_file/fd_file.h"
 #include "class_linker.h"
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 47ffb4e..cb3e8de 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -39,6 +39,7 @@
 #include "art_field-inl.h"
 #include "art_method-inl.h"
 #include "base/bit_utils.h"
+#include "base/file_utils.h"
 #include "base/memory_tool.h"
 #include "base/mutex.h"
 #include "base/systrace.h"
diff --git a/runtime/utils.cc b/runtime/utils.cc
index 1f6bd74..f6533a7 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -18,41 +18,20 @@
 
 #include <inttypes.h>
 #include <pthread.h>
-#include <sys/mman.h>  // For madvise
 #include <sys/stat.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
 
-// We need dladdr.
-#ifndef __APPLE__
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#define DEFINED_GNU_SOURCE
-#endif
-#include <dlfcn.h>
-#include <libgen.h>
-#ifdef DEFINED_GNU_SOURCE
-#undef _GNU_SOURCE
-#undef DEFINED_GNU_SOURCE
-#endif
-#endif
-
-
 #include <memory>
 
 #include "android-base/stringprintf.h"
 #include "android-base/strings.h"
 
-#include "base/stl_util.h"
-#include "base/unix_file/fd_file.h"
+#include "base/file_utils.h"
 #include "dex_file-inl.h"
-#include "dex_file_loader.h"
-#include "dex_instruction.h"
-#include "oat_quick_method_header.h"
 #include "os.h"
-#include "scoped_thread_state_change-inl.h"
 #include "utf-inl.h"
 
 #if defined(__APPLE__)
@@ -92,78 +71,6 @@
   return result;
 }
 
-bool ReadFileToString(const std::string& file_name, std::string* result) {
-  File file(file_name, O_RDONLY, false);
-  if (!file.IsOpened()) {
-    return false;
-  }
-
-  std::vector<char> buf(8 * KB);
-  while (true) {
-    int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[0], buf.size()));
-    if (n == -1) {
-      return false;
-    }
-    if (n == 0) {
-      return true;
-    }
-    result->append(&buf[0], n);
-  }
-}
-
-bool PrintFileToLog(const std::string& file_name, LogSeverity level) {
-  File file(file_name, O_RDONLY, false);
-  if (!file.IsOpened()) {
-    return false;
-  }
-
-  constexpr size_t kBufSize = 256;  // Small buffer. Avoid stack overflow and stack size warnings.
-  char buf[kBufSize + 1];           // +1 for terminator.
-  size_t filled_to = 0;
-  while (true) {
-    DCHECK_LT(filled_to, kBufSize);
-    int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[filled_to], kBufSize - filled_to));
-    if (n <= 0) {
-      // Print the rest of the buffer, if it exists.
-      if (filled_to > 0) {
-        buf[filled_to] = 0;
-        LOG(level) << buf;
-      }
-      return n == 0;
-    }
-    // Scan for '\n'.
-    size_t i = filled_to;
-    bool found_newline = false;
-    for (; i < filled_to + n; ++i) {
-      if (buf[i] == '\n') {
-        // Found a line break, that's something to print now.
-        buf[i] = 0;
-        LOG(level) << buf;
-        // Copy the rest to the front.
-        if (i + 1 < filled_to + n) {
-          memmove(&buf[0], &buf[i + 1], filled_to + n - i - 1);
-          filled_to = filled_to + n - i - 1;
-        } else {
-          filled_to = 0;
-        }
-        found_newline = true;
-        break;
-      }
-    }
-    if (found_newline) {
-      continue;
-    } else {
-      filled_to += n;
-      // Check if we must flush now.
-      if (filled_to == kBufSize) {
-        buf[kBufSize] = 0;
-        LOG(level) << buf;
-        filled_to = 0;
-      }
-    }
-  }
-}
-
 void AppendPrettyDescriptor(const char* descriptor, std::string* result) {
   // Count the number of '['s to get the dimensionality.
   const char* c = descriptor;
@@ -718,197 +625,6 @@
   *task_cpu = strtoull(fields[36].c_str(), nullptr, 10);
 }
 
-std::string GetAndroidRootSafe(std::string* error_msg) {
-  // Prefer ANDROID_ROOT if it's set.
-  const char* android_dir = getenv("ANDROID_ROOT");
-  if (android_dir != nullptr) {
-    if (!OS::DirectoryExists(android_dir)) {
-      *error_msg = StringPrintf("Failed to find ANDROID_ROOT directory %s", android_dir);
-      return "";
-    }
-    return android_dir;
-  }
-
-  // Check where libart is from, and derive from there. Only do this for non-Mac.
-#ifndef __APPLE__
-  {
-    Dl_info info;
-    if (dladdr(reinterpret_cast<const void*>(&GetAndroidRootSafe), /* out */ &info) != 0) {
-      // Make a duplicate of the fname so dirname can modify it.
-      UniqueCPtr<char> fname(strdup(info.dli_fname));
-
-      char* dir1 = dirname(fname.get());  // This is the lib directory.
-      char* dir2 = dirname(dir1);         // This is the "system" directory.
-      if (OS::DirectoryExists(dir2)) {
-        std::string tmp = dir2;  // Make a copy here so that fname can be released.
-        return tmp;
-      }
-    }
-  }
-#endif
-
-  // Try "/system".
-  if (!OS::DirectoryExists("/system")) {
-    *error_msg = "Failed to find ANDROID_ROOT directory /system";
-    return "";
-  }
-  return "/system";
-}
-
-std::string GetAndroidRoot() {
-  std::string error_msg;
-  std::string ret = GetAndroidRootSafe(&error_msg);
-  if (ret.empty()) {
-    LOG(FATAL) << error_msg;
-    UNREACHABLE();
-  }
-  return ret;
-}
-
-
-static const char* GetAndroidDirSafe(const char* env_var,
-                                     const char* default_dir,
-                                     std::string* error_msg) {
-  const char* android_dir = getenv(env_var);
-  if (android_dir == nullptr) {
-    if (OS::DirectoryExists(default_dir)) {
-      android_dir = default_dir;
-    } else {
-      *error_msg = StringPrintf("%s not set and %s does not exist", env_var, default_dir);
-      return nullptr;
-    }
-  }
-  if (!OS::DirectoryExists(android_dir)) {
-    *error_msg = StringPrintf("Failed to find %s directory %s", env_var, android_dir);
-    return nullptr;
-  }
-  return android_dir;
-}
-
-static const char* GetAndroidDir(const char* env_var, const char* default_dir) {
-  std::string error_msg;
-  const char* dir = GetAndroidDirSafe(env_var, default_dir, &error_msg);
-  if (dir != nullptr) {
-    return dir;
-  } else {
-    LOG(FATAL) << error_msg;
-    return nullptr;
-  }
-}
-
-const char* GetAndroidData() {
-  return GetAndroidDir("ANDROID_DATA", "/data");
-}
-
-const char* GetAndroidDataSafe(std::string* error_msg) {
-  return GetAndroidDirSafe("ANDROID_DATA", "/data", error_msg);
-}
-
-std::string GetDefaultBootImageLocation(std::string* error_msg) {
-  std::string android_root = GetAndroidRootSafe(error_msg);
-  if (android_root.empty()) {
-    return "";
-  }
-  return StringPrintf("%s/framework/boot.art", android_root.c_str());
-}
-
-void GetDalvikCache(const char* subdir, const bool create_if_absent, std::string* dalvik_cache,
-                    bool* have_android_data, bool* dalvik_cache_exists, bool* is_global_cache) {
-  CHECK(subdir != nullptr);
-  std::string error_msg;
-  const char* android_data = GetAndroidDataSafe(&error_msg);
-  if (android_data == nullptr) {
-    *have_android_data = false;
-    *dalvik_cache_exists = false;
-    *is_global_cache = false;
-    return;
-  } else {
-    *have_android_data = true;
-  }
-  const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data));
-  *dalvik_cache = dalvik_cache_root + subdir;
-  *dalvik_cache_exists = OS::DirectoryExists(dalvik_cache->c_str());
-  *is_global_cache = strcmp(android_data, "/data") == 0;
-  if (create_if_absent && !*dalvik_cache_exists && !*is_global_cache) {
-    // Don't create the system's /data/dalvik-cache/... because it needs special permissions.
-    *dalvik_cache_exists = ((mkdir(dalvik_cache_root.c_str(), 0700) == 0 || errno == EEXIST) &&
-                            (mkdir(dalvik_cache->c_str(), 0700) == 0 || errno == EEXIST));
-  }
-}
-
-std::string GetDalvikCache(const char* subdir) {
-  CHECK(subdir != nullptr);
-  const char* android_data = GetAndroidData();
-  const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data));
-  const std::string dalvik_cache = dalvik_cache_root + subdir;
-  if (!OS::DirectoryExists(dalvik_cache.c_str())) {
-    // TODO: Check callers. Traditional behavior is to not abort.
-    return "";
-  }
-  return dalvik_cache;
-}
-
-bool GetDalvikCacheFilename(const char* location, const char* cache_location,
-                            std::string* filename, std::string* error_msg) {
-  if (location[0] != '/') {
-    *error_msg = StringPrintf("Expected path in location to be absolute: %s", location);
-    return false;
-  }
-  std::string cache_file(&location[1]);  // skip leading slash
-  if (!android::base::EndsWith(location, ".dex") &&
-      !android::base::EndsWith(location, ".art") &&
-      !android::base::EndsWith(location, ".oat")) {
-    cache_file += "/";
-    cache_file += DexFileLoader::kClassesDex;
-  }
-  std::replace(cache_file.begin(), cache_file.end(), '/', '@');
-  *filename = StringPrintf("%s/%s", cache_location, cache_file.c_str());
-  return true;
-}
-
-std::string GetVdexFilename(const std::string& oat_location) {
-  return ReplaceFileExtension(oat_location, "vdex");
-}
-
-static void InsertIsaDirectory(const InstructionSet isa, std::string* filename) {
-  // in = /foo/bar/baz
-  // out = /foo/bar/<isa>/baz
-  size_t pos = filename->rfind('/');
-  CHECK_NE(pos, std::string::npos) << *filename << " " << isa;
-  filename->insert(pos, "/", 1);
-  filename->insert(pos + 1, GetInstructionSetString(isa));
-}
-
-std::string GetSystemImageFilename(const char* location, const InstructionSet isa) {
-  // location = /system/framework/boot.art
-  // filename = /system/framework/<isa>/boot.art
-  std::string filename(location);
-  InsertIsaDirectory(isa, &filename);
-  return filename;
-}
-
-bool FileExists(const std::string& filename) {
-  struct stat buffer;
-  return stat(filename.c_str(), &buffer) == 0;
-}
-
-bool FileExistsAndNotEmpty(const std::string& filename) {
-  struct stat buffer;
-  if (stat(filename.c_str(), &buffer) != 0) {
-    return false;
-  }
-  return buffer.st_size > 0;
-}
-
-std::string ReplaceFileExtension(const std::string& filename, const std::string& new_extension) {
-  const size_t last_ext = filename.find_last_of('.');
-  if (last_ext == std::string::npos) {
-    return filename + "." + new_extension;
-  } else {
-    return filename.substr(0, last_ext + 1) + new_extension;
-  }
-}
-
 std::string PrettyDescriptor(Primitive::Type type) {
   return PrettyDescriptor(Primitive::Descriptor(type));
 }
@@ -952,30 +668,10 @@
   *parsed_value = value;
 }
 
-int64_t GetFileSizeBytes(const std::string& filename) {
-  struct stat stat_buf;
-  int rc = stat(filename.c_str(), &stat_buf);
-  return rc == 0 ? stat_buf.st_size : -1;
-}
-
 void SleepForever() {
   while (true) {
     usleep(1000000);
   }
 }
 
-int MadviseLargestPageAlignedRegion(const uint8_t* begin, const uint8_t* end, int advice) {
-  DCHECK_LE(begin, end);
-  begin = AlignUp(begin, kPageSize);
-  end = AlignDown(end, kPageSize);
-  if (begin < end) {
-    int result = madvise(const_cast<uint8_t*>(begin), end - begin, advice);
-    if (result != 0) {
-      PLOG(WARNING) << "madvise failed " << result;
-    }
-    return result;
-  }
-  return 0;
-}
-
 }  // namespace art
diff --git a/runtime/utils.h b/runtime/utils.h
index fbf812a..ede32dc 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -20,12 +20,8 @@
 #include <pthread.h>
 #include <stdlib.h>
 
-#include <limits>
-#include <memory>
 #include <random>
 #include <string>
-#include <type_traits>
-#include <vector>
 
 #include "arch/instruction_set.h"
 #include "base/casts.h"
@@ -118,9 +114,6 @@
 // additionally allowing names that begin with '<' and end with '>'.
 bool IsValidMemberName(const char* s);
 
-bool ReadFileToString(const std::string& file_name, std::string* result);
-bool PrintFileToLog(const std::string& file_name, LogSeverity level);
-
 // Splits a string using the given separator character into a vector of
 // strings. Empty strings will be omitted.
 void Split(const std::string& s, char separator, std::vector<std::string>* result);
@@ -131,58 +124,12 @@
 // Returns the given thread's name.
 std::string GetThreadName(pid_t tid);
 
-// Reads data from "/proc/self/task/${tid}/stat".
-void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu);
-
 // Sets the name of the current thread. The name may be truncated to an
 // implementation-defined limit.
 void SetThreadName(const char* thread_name);
 
-// Find $ANDROID_ROOT, /system, or abort.
-std::string GetAndroidRoot();
-// Find $ANDROID_ROOT, /system, or return an empty string.
-std::string GetAndroidRootSafe(std::string* error_msg);
-
-// Find $ANDROID_DATA, /data, or abort.
-const char* GetAndroidData();
-// Find $ANDROID_DATA, /data, or return null.
-const char* GetAndroidDataSafe(std::string* error_msg);
-
-// Returns the default boot image location (ANDROID_ROOT/framework/boot.art).
-// Returns an empty string if ANDROID_ROOT is not set.
-std::string GetDefaultBootImageLocation(std::string* error_msg);
-
-// Returns the dalvik-cache location, with subdir appended. Returns the empty string if the cache
-// could not be found.
-std::string GetDalvikCache(const char* subdir);
-// Return true if we found the dalvik cache and stored it in the dalvik_cache argument.
-// have_android_data will be set to true if we have an ANDROID_DATA that exists,
-// dalvik_cache_exists will be true if there is a dalvik-cache directory that is present.
-// The flag is_global_cache tells whether this cache is /data/dalvik-cache.
-void GetDalvikCache(const char* subdir, bool create_if_absent, std::string* dalvik_cache,
-                    bool* have_android_data, bool* dalvik_cache_exists, bool* is_global_cache);
-
-// Returns the absolute dalvik-cache path for a DexFile or OatFile. The path returned will be
-// rooted at cache_location.
-bool GetDalvikCacheFilename(const char* file_location, const char* cache_location,
-                            std::string* filename, std::string* error_msg);
-
-// Returns the system location for an image
-std::string GetSystemImageFilename(const char* location, InstructionSet isa);
-
-// Returns the vdex filename for the given oat filename.
-std::string GetVdexFilename(const std::string& oat_filename);
-
-// Returns true if the file exists.
-bool FileExists(const std::string& filename);
-bool FileExistsAndNotEmpty(const std::string& filename);
-
-// Returns `filename` with the text after the last occurrence of '.' replaced with
-// `extension`. If `filename` does not contain a period, returns a string containing `filename`,
-// a period, and `new_extension`.
-// Example: ReplaceFileExtension("foo.bar", "abc") == "foo.abc"
-//          ReplaceFileExtension("foo", "abc") == "foo.abc"
-std::string ReplaceFileExtension(const std::string& filename, const std::string& new_extension);
+// Reads data from "/proc/self/task/${tid}/stat".
+void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu);
 
 class VoidFunctor {
  public:
@@ -273,9 +220,6 @@
   return dist(rng);
 }
 
-// Return the file size in bytes or -1 if the file does not exists.
-int64_t GetFileSizeBytes(const std::string& filename);
-
 // Sleep forever and never come back.
 NO_RETURN void SleepForever();
 
@@ -335,9 +279,6 @@
   return (opnd < 0) ? -1 : ((opnd == 0) ? 0 : 1);
 }
 
-// Madvise the largest page aligned region within begin and end.
-int MadviseLargestPageAlignedRegion(const uint8_t* begin, const uint8_t* end, int advice);
-
 template <typename Func, typename... Args>
 static inline void CheckedCall(const Func& function, const char* what, Args... args) {
   int rc = function(args...);
diff --git a/runtime/utils_test.cc b/runtime/utils_test.cc
index e846c98..efb20ba 100644
--- a/runtime/utils_test.cc
+++ b/runtime/utils_test.cc
@@ -20,6 +20,7 @@
 #include <stdlib.h>
 
 #include "base/enums.h"
+#include "base/file_utils.h"
 #include "base/stl_util.h"
 #include "class_linker-inl.h"
 #include "common_runtime_test.h"
diff --git a/test/137-cfi/cfi.cc b/test/137-cfi/cfi.cc
index ad705c5..58b33be 100644
--- a/test/137-cfi/cfi.cc
+++ b/test/137-cfi/cfi.cc
@@ -28,6 +28,7 @@
 #include <backtrace/Backtrace.h>
 #include "android-base/stringprintf.h"
 
+#include "base/file_utils.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "gc/heap.h"