Merge "Avoid re-mapping dex file that's in local memory."
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index bd71cb5..ef8ffbe 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -234,7 +234,16 @@
         old_root_dir.reset();
     }
 
-    Modprobe m({"/lib/modules"});
+    std::string module_load_file = "modules.load";
+    if (IsRecoveryMode() && !ForceNormalBoot(cmdline)) {
+        struct stat fileStat;
+        std::string recovery_load_path = "/lib/modules/modules.load.recovery";
+        if (!stat(recovery_load_path.c_str(), &fileStat)) {
+            module_load_file = "modules.load.recovery";
+        }
+    }
+
+    Modprobe m({"/lib/modules"}, module_load_file);
     auto want_console = ALLOW_FIRST_STAGE_CONSOLE && FirstStageConsole(cmdline);
     if (!m.LoadListedModules(!want_console)) {
         if (want_console) {
diff --git a/libmodprobe/include/modprobe/modprobe.h b/libmodprobe/include/modprobe/modprobe.h
index ee6ae7a..297036e 100644
--- a/libmodprobe/include/modprobe/modprobe.h
+++ b/libmodprobe/include/modprobe/modprobe.h
@@ -24,7 +24,7 @@
 
 class Modprobe {
   public:
-    Modprobe(const std::vector<std::string>&);
+    Modprobe(const std::vector<std::string>&, const std::string load_file = "modules.load");
 
     bool LoadListedModules(bool strict = true);
     bool LoadWithAliases(const std::string& module_name, bool strict,
diff --git a/libmodprobe/libmodprobe.cpp b/libmodprobe/libmodprobe.cpp
index f22bbf1..d193796 100644
--- a/libmodprobe/libmodprobe.cpp
+++ b/libmodprobe/libmodprobe.cpp
@@ -312,7 +312,7 @@
     }
 }
 
-Modprobe::Modprobe(const std::vector<std::string>& base_paths) {
+Modprobe::Modprobe(const std::vector<std::string>& base_paths, const std::string load_file) {
     using namespace std::placeholders;
 
     for (const auto& base_path : base_paths) {
@@ -326,7 +326,7 @@
         ParseCfg(base_path + "/modules.softdep", softdep_callback);
 
         auto load_callback = std::bind(&Modprobe::ParseLoadCallback, this, _1);
-        ParseCfg(base_path + "/modules.load", load_callback);
+        ParseCfg(base_path + "/" + load_file, load_callback);
 
         auto options_callback = std::bind(&Modprobe::ParseOptionsCallback, this, _1);
         ParseCfg(base_path + "/modules.options", options_callback);
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index 8f9774f..7658d5c 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -1009,19 +1009,17 @@
 // the data appended to it.
 class MemoryWriter : public zip_archive::Writer {
  public:
-  static MemoryWriter Create(uint8_t* buf, size_t size, const ZipEntry64* entry) {
+  static std::unique_ptr<MemoryWriter> Create(uint8_t* buf, size_t size, const ZipEntry64* entry) {
     const uint64_t declared_length = entry->uncompressed_length;
     if (declared_length > size) {
       ALOGW("Zip: file size %" PRIu64 " is larger than the buffer size %zu.", declared_length,
             size);
-      return MemoryWriter{nullptr, 0};
+      return nullptr;
     }
 
-    return MemoryWriter(buf, size);
+    return std::unique_ptr<MemoryWriter>(new MemoryWriter(buf, size));
   }
 
-  bool IsValid() const { return buf_ != nullptr; }
-
   virtual bool Append(uint8_t* buf, size_t buf_size) override {
     if (size_ < buf_size || bytes_written_ > size_ - buf_size) {
       ALOGW("Zip: Unexpected size %zu (declared) vs %zu (actual)", size_,
@@ -1053,17 +1051,17 @@
   // block device).
   //
   // Returns a valid FileWriter on success, |nullptr| if an error occurred.
-  static FileWriter Create(int fd, const ZipEntry64* entry) {
+  static std::unique_ptr<FileWriter> Create(int fd, const ZipEntry64* entry) {
     const uint64_t declared_length = entry->uncompressed_length;
     const off64_t current_offset = lseek64(fd, 0, SEEK_CUR);
     if (current_offset == -1) {
       ALOGW("Zip: unable to seek to current location on fd %d: %s", fd, strerror(errno));
-      return FileWriter{};
+      return nullptr;
     }
 
     if (declared_length > SIZE_MAX || declared_length > INT64_MAX) {
       ALOGW("Zip: file size %" PRIu64 " is too large to extract.", declared_length);
-      return FileWriter{};
+      return nullptr;
     }
 
 #if defined(__linux__)
@@ -1081,7 +1079,7 @@
       if (result == -1 && errno == ENOSPC) {
         ALOGW("Zip: unable to allocate %" PRIu64 " bytes at offset %" PRId64 ": %s",
               declared_length, static_cast<int64_t>(current_offset), strerror(errno));
-        return FileWriter{};
+        return nullptr;
       }
     }
 #endif  // __linux__
@@ -1089,7 +1087,7 @@
     struct stat sb;
     if (fstat(fd, &sb) == -1) {
       ALOGW("Zip: unable to fstat file: %s", strerror(errno));
-      return FileWriter{};
+      return nullptr;
     }
 
     // Block device doesn't support ftruncate(2).
@@ -1098,11 +1096,11 @@
       if (result == -1) {
         ALOGW("Zip: unable to truncate file to %" PRId64 ": %s",
               static_cast<int64_t>(declared_length + current_offset), strerror(errno));
-        return FileWriter{};
+        return nullptr;
       }
     }
 
-    return FileWriter(fd, declared_length);
+    return std::unique_ptr<FileWriter>(new FileWriter(fd, declared_length));
   }
 
   FileWriter(FileWriter&& other) noexcept
@@ -1112,8 +1110,6 @@
     other.fd_ = -1;
   }
 
-  bool IsValid() const { return fd_ != -1; }
-
   virtual bool Append(uint8_t* buf, size_t buf_size) override {
     if (declared_length_ < buf_size || total_bytes_written_ > declared_length_ - buf_size) {
       ALOGW("Zip: Unexpected size %zu  (declared) vs %zu (actual)", declared_length_,
@@ -1365,11 +1361,11 @@
 int32_t ExtractToMemory(ZipArchiveHandle archive, const ZipEntry64* entry, uint8_t* begin,
                         size_t size) {
   auto writer = MemoryWriter::Create(begin, size, entry);
-  if (!writer.IsValid()) {
+  if (!writer) {
     return kIoError;
   }
 
-  return ExtractToWriter(archive, entry, &writer);
+  return ExtractToWriter(archive, entry, writer.get());
 }
 
 int32_t ExtractEntryToFile(ZipArchiveHandle archive, const ZipEntry* entry, int fd) {
@@ -1379,11 +1375,11 @@
 
 int32_t ExtractEntryToFile(ZipArchiveHandle archive, const ZipEntry64* entry, int fd) {
   auto writer = FileWriter::Create(fd, entry);
-  if (!writer.IsValid()) {
+  if (!writer) {
     return kIoError;
   }
 
-  return ExtractToWriter(archive, entry, &writer);
+  return ExtractToWriter(archive, entry, writer.get());
 }
 
 int GetFileDescriptor(const ZipArchiveHandle archive) {
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
index 3d4e580..f5429be 100644
--- a/libziparchive/zip_archive_test.cc
+++ b/libziparchive/zip_archive_test.cc
@@ -344,8 +344,8 @@
   // Known facts about a.txt, from zipinfo -v.
   ASSERT_EQ(63, data.offset);
   ASSERT_EQ(kCompressDeflated, data.method);
-  ASSERT_EQ(static_cast<uint32_t>(17), data.uncompressed_length);
-  ASSERT_EQ(static_cast<uint32_t>(13), data.compressed_length);
+  ASSERT_EQ(17u, data.uncompressed_length);
+  ASSERT_EQ(13u, data.compressed_length);
   ASSERT_EQ(0x950821c5, data.crc32);
   ASSERT_EQ(static_cast<uint32_t>(0x438a8005), data.mod_time);
 
@@ -505,9 +505,12 @@
 
   ZipEntry64 entry;
   ASSERT_EQ(0, FindEntry(handle, "empty.txt", &entry));
-  ASSERT_EQ(static_cast<uint32_t>(0), entry.uncompressed_length);
+  ASSERT_EQ(0u, entry.uncompressed_length);
+  // Extraction to a 1 byte buffer should succeed.
   uint8_t buffer[1];
   ASSERT_EQ(0, ExtractToMemory(handle, &entry, buffer, 1));
+  // Extraction to an empty buffer should succeed.
+  ASSERT_EQ(0, ExtractToMemory(handle, &entry, nullptr, 0));
 
   TemporaryFile tmp_output_file;
   ASSERT_NE(-1, tmp_output_file.fd);
@@ -782,7 +785,7 @@
   // "abdcdefghijk").
   ZipEntry64 entry;
   ASSERT_EQ(0, FindEntry(handle, "name", &entry));
-  ASSERT_EQ(static_cast<uint32_t>(12), entry.uncompressed_length);
+  ASSERT_EQ(12u, entry.uncompressed_length);
 
   entry_out->resize(12);
   (*error_code_out) = ExtractToMemory(handle, &entry, &((*entry_out)[0]), 12);