Merge "Add /dev/stdin, /dev/stdout, and /dev/stderr."
diff --git a/fastboot/fastboot_driver.cpp b/fastboot/fastboot_driver.cpp
index 55ca65d..c508abe 100644
--- a/fastboot/fastboot_driver.cpp
+++ b/fastboot/fastboot_driver.cpp
@@ -220,10 +220,10 @@
     return HandleResponse(response, info);
 }
 
-RetCode FastBootDriver::Download(sparse_file* s, std::string* response,
+RetCode FastBootDriver::Download(sparse_file* s, bool use_crc, std::string* response,
                                  std::vector<std::string>* info) {
     error_ = "";
-    int64_t size = sparse_file_len(s, true, false);
+    int64_t size = sparse_file_len(s, true, use_crc);
     if (size <= 0 || size > MAX_DOWNLOAD_SIZE) {
         error_ = "Sparse file is too large or invalid";
         return BAD_ARG;
@@ -247,7 +247,7 @@
         return data->self->SparseWriteCallback(data->tpbuf, cbuf, len);
     };
 
-    if (sparse_file_callback(s, true, false, cb, &cb_priv) < 0) {
+    if (sparse_file_callback(s, true, use_crc, cb, &cb_priv) < 0) {
         error_ = "Error reading sparse file";
         return IO_ERROR;
     }
diff --git a/fastboot/fastboot_driver.h b/fastboot/fastboot_driver.h
index dd199c0..fae9dc4 100644
--- a/fastboot/fastboot_driver.h
+++ b/fastboot/fastboot_driver.h
@@ -74,7 +74,7 @@
     // This will be removed after fastboot is modified to use a vector
     RetCode Download(const char* buf, uint32_t size, std::string* response = nullptr,
                      std::vector<std::string>* info = nullptr);
-    RetCode Download(sparse_file* s, std::string* response = nullptr,
+    RetCode Download(sparse_file* s, bool use_crc = false, std::string* response = nullptr,
                      std::vector<std::string>* info = nullptr);
     RetCode Erase(const std::string& part, std::string* response = nullptr,
                   std::vector<std::string>* info = nullptr);
diff --git a/fs_mgr/liblp/images.cpp b/fs_mgr/liblp/images.cpp
index a361a5d..742b1d0 100644
--- a/fs_mgr/liblp/images.cpp
+++ b/fs_mgr/liblp/images.cpp
@@ -38,12 +38,24 @@
         PERROR << __PRETTY_FUNCTION__ << "lseek failed: offset " << LP_METADATA_GEOMETRY_SIZE;
         return nullptr;
     }
-    std::unique_ptr<LpMetadata> metadata = ParseMetadata(fd);
-    if (!metadata) {
+    return ParseMetadata(geometry, fd);
+}
+
+std::unique_ptr<LpMetadata> ReadFromImageBlob(const void* data, size_t bytes) {
+    if (bytes < LP_METADATA_GEOMETRY_SIZE) {
+        LERROR << __PRETTY_FUNCTION__ << ": " << bytes << " is smaller than geometry header";
         return nullptr;
     }
-    metadata->geometry = geometry;
-    return metadata;
+
+    LpMetadataGeometry geometry;
+    if (!ParseGeometry(data, &geometry)) {
+        return nullptr;
+    }
+
+    const uint8_t* metadata_buffer =
+            reinterpret_cast<const uint8_t*>(data) + LP_METADATA_GEOMETRY_SIZE;
+    size_t metadata_buffer_size = bytes - LP_METADATA_GEOMETRY_SIZE;
+    return ParseMetadata(geometry, metadata_buffer, metadata_buffer_size);
 }
 
 std::unique_ptr<LpMetadata> ReadFromImageFile(const char* file) {
diff --git a/fs_mgr/liblp/include/liblp/liblp.h b/fs_mgr/liblp/include/liblp/liblp.h
index 627aa8c..6da24f6 100644
--- a/fs_mgr/liblp/include/liblp/liblp.h
+++ b/fs_mgr/liblp/include/liblp/liblp.h
@@ -42,8 +42,7 @@
 // existing geometry, and should not be used for normal partition table
 // updates. False can be returned if the geometry is incompatible with the
 // block device or an I/O error occurs.
-bool FlashPartitionTable(const std::string& block_device, const LpMetadata& metadata,
-                         uint32_t slot_number);
+bool FlashPartitionTable(const std::string& block_device, const LpMetadata& metadata);
 
 // Update the partition table for a given metadata slot number. False is
 // returned if an error occurs, which can include:
@@ -64,6 +63,7 @@
                        const std::map<std::string, std::string>& images);
 bool WriteToImageFile(const char* file, const LpMetadata& metadata);
 std::unique_ptr<LpMetadata> ReadFromImageFile(const char* file);
+std::unique_ptr<LpMetadata> ReadFromImageBlob(const void* data, size_t bytes);
 
 // Helper to extract safe C++ strings from partition info.
 std::string GetPartitionName(const LpMetadataPartition& partition);
diff --git a/fs_mgr/liblp/io_test.cpp b/fs_mgr/liblp/io_test.cpp
index 638f4b3..329a901 100644
--- a/fs_mgr/liblp/io_test.cpp
+++ b/fs_mgr/liblp/io_test.cpp
@@ -103,7 +103,7 @@
     if (!exported) {
         return {};
     }
-    if (!FlashPartitionTable(fd, *exported.get(), 0)) {
+    if (!FlashPartitionTable(fd, *exported.get())) {
         return {};
     }
     return fd;
@@ -132,7 +132,7 @@
     unique_fd fd = CreateFakeDisk();
     ASSERT_GE(fd, 0);
 
-    EXPECT_FALSE(FlashPartitionTable(fd, *exported.get(), 0));
+    EXPECT_FALSE(FlashPartitionTable(fd, *exported.get()));
 }
 
 // Test the basics of flashing a partition and reading it back.
@@ -147,7 +147,7 @@
     // Export and flash.
     unique_ptr<LpMetadata> exported = builder->Export();
     ASSERT_NE(exported, nullptr);
-    ASSERT_TRUE(FlashPartitionTable(fd, *exported.get(), 0));
+    ASSERT_TRUE(FlashPartitionTable(fd, *exported.get()));
 
     // Read back. Note that some fields are only filled in during
     // serialization, so exported and imported will not be identical. For
@@ -354,8 +354,7 @@
     ASSERT_GE(fd, 0);
 
     // Check that we are able to write our table.
-    ASSERT_TRUE(FlashPartitionTable(fd, *exported.get(), 0));
-    ASSERT_TRUE(UpdatePartitionTable(fd, *exported.get(), 1));
+    ASSERT_TRUE(FlashPartitionTable(fd, *exported.get()));
 
     // Check that adding one more partition overflows the metadata allotment.
     partition = builder->AddPartition("final", TEST_GUID, LP_PARTITION_ATTR_NONE);
@@ -395,6 +394,27 @@
     ASSERT_NE(imported, nullptr);
 }
 
+// Test that we can read images from buffers.
+TEST(liblp, ImageFilesInMemory) {
+    unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder();
+    ASSERT_NE(builder, nullptr);
+    ASSERT_TRUE(AddDefaultPartitions(builder.get()));
+    unique_ptr<LpMetadata> exported = builder->Export();
+
+    unique_fd fd(syscall(__NR_memfd_create, "image_file", 0));
+    ASSERT_GE(fd, 0);
+    ASSERT_TRUE(WriteToImageFile(fd, *exported.get()));
+
+    int64_t offset = SeekFile64(fd, 0, SEEK_CUR);
+    ASSERT_GE(offset, 0);
+    ASSERT_EQ(SeekFile64(fd, 0, SEEK_SET), 0);
+
+    size_t bytes = static_cast<size_t>(offset);
+    std::unique_ptr<char[]> buffer = std::make_unique<char[]>(bytes);
+    ASSERT_TRUE(android::base::ReadFully(fd, buffer.get(), bytes));
+    ASSERT_NE(ReadFromImageBlob(buffer.get(), bytes), nullptr);
+}
+
 class BadWriter {
   public:
     // When requested, write garbage instead of the requested bytes, then
diff --git a/fs_mgr/liblp/reader.cpp b/fs_mgr/liblp/reader.cpp
index 117da59..117f5d5 100644
--- a/fs_mgr/liblp/reader.cpp
+++ b/fs_mgr/liblp/reader.cpp
@@ -30,9 +30,45 @@
 namespace android {
 namespace fs_mgr {
 
-// Parse an LpMetadataGeometry from a buffer. The buffer must be at least
-// LP_METADATA_GEOMETRY_SIZE bytes in size.
-static bool ParseGeometry(const void* buffer, LpMetadataGeometry* geometry) {
+// Helper class for reading descriptors and memory buffers in the same manner.
+class Reader {
+  public:
+    virtual ~Reader(){};
+    virtual bool ReadFully(void* buffer, size_t length) = 0;
+};
+
+class FileReader final : public Reader {
+  public:
+    explicit FileReader(int fd) : fd_(fd) {}
+    bool ReadFully(void* buffer, size_t length) override {
+        return android::base::ReadFully(fd_, buffer, length);
+    }
+
+  private:
+    int fd_;
+};
+
+class MemoryReader final : public Reader {
+  public:
+    MemoryReader(const void* buffer, size_t size)
+        : buffer_(reinterpret_cast<const uint8_t*>(buffer)), size_(size), pos_(0) {}
+    bool ReadFully(void* out, size_t length) override {
+        if (size_ - pos_ < length) {
+            errno = EINVAL;
+            return false;
+        }
+        memcpy(out, buffer_ + pos_, length);
+        pos_ += length;
+        return true;
+    }
+
+  private:
+    const uint8_t* buffer_;
+    size_t size_;
+    size_t pos_;
+};
+
+bool ParseGeometry(const void* buffer, LpMetadataGeometry* geometry) {
     static_assert(sizeof(*geometry) <= LP_METADATA_GEOMETRY_SIZE);
     memcpy(geometry, buffer, sizeof(*geometry));
 
@@ -171,16 +207,18 @@
 
 // Parse and validate all metadata at the current position in the given file
 // descriptor.
-std::unique_ptr<LpMetadata> ParseMetadata(int fd) {
+static std::unique_ptr<LpMetadata> ParseMetadata(const LpMetadataGeometry& geometry,
+                                                 Reader* reader) {
     // First read and validate the header.
     std::unique_ptr<LpMetadata> metadata = std::make_unique<LpMetadata>();
-    if (!android::base::ReadFully(fd, &metadata->header, sizeof(metadata->header))) {
+    if (!reader->ReadFully(&metadata->header, sizeof(metadata->header))) {
         PERROR << __PRETTY_FUNCTION__ << "read " << sizeof(metadata->header) << "bytes failed";
         return nullptr;
     }
     if (!ValidateMetadataHeader(metadata->header)) {
         return nullptr;
     }
+    metadata->geometry = geometry;
 
     LpMetadataHeader& header = metadata->header;
 
@@ -191,7 +229,7 @@
         LERROR << "Out of memory reading logical partition tables.";
         return nullptr;
     }
-    if (!android::base::ReadFully(fd, buffer.get(), header.tables_size)) {
+    if (!reader->ReadFully(buffer.get(), header.tables_size)) {
         PERROR << __PRETTY_FUNCTION__ << "read " << header.tables_size << "bytes failed";
         return nullptr;
     }
@@ -231,10 +269,20 @@
 
         metadata->extents.push_back(extent);
     }
-
     return metadata;
 }
 
+std::unique_ptr<LpMetadata> ParseMetadata(const LpMetadataGeometry& geometry, const void* buffer,
+                                          size_t size) {
+    MemoryReader reader(buffer, size);
+    return ParseMetadata(geometry, &reader);
+}
+
+std::unique_ptr<LpMetadata> ParseMetadata(const LpMetadataGeometry& geometry, int fd) {
+    FileReader reader(fd);
+    return ParseMetadata(geometry, &reader);
+}
+
 std::unique_ptr<LpMetadata> ReadPrimaryMetadata(int fd, const LpMetadataGeometry& geometry,
                                                 uint32_t slot_number) {
     int64_t offset = GetPrimaryMetadataOffset(geometry, slot_number);
@@ -242,7 +290,7 @@
         PERROR << __PRETTY_FUNCTION__ << "lseek failed: offset " << offset;
         return nullptr;
     }
-    return ParseMetadata(fd);
+    return ParseMetadata(geometry, fd);
 }
 
 std::unique_ptr<LpMetadata> ReadBackupMetadata(int fd, const LpMetadataGeometry& geometry,
@@ -252,7 +300,7 @@
         PERROR << __PRETTY_FUNCTION__ << "lseek failed: offset " << offset;
         return nullptr;
     }
-    return ParseMetadata(fd);
+    return ParseMetadata(geometry, fd);
 }
 
 std::unique_ptr<LpMetadata> ReadMetadata(int fd, uint32_t slot_number) {
@@ -268,13 +316,10 @@
 
     // Read the priamry copy, and if that fails, try the backup.
     std::unique_ptr<LpMetadata> metadata = ReadPrimaryMetadata(fd, geometry, slot_number);
-    if (!metadata) {
-        metadata = ReadBackupMetadata(fd, geometry, slot_number);
-    }
     if (metadata) {
-        metadata->geometry = geometry;
+        return metadata;
     }
-    return metadata;
+    return ReadBackupMetadata(fd, geometry, slot_number);
 }
 
 std::unique_ptr<LpMetadata> ReadMetadata(const char* block_device, uint32_t slot_number) {
diff --git a/fs_mgr/liblp/reader.h b/fs_mgr/liblp/reader.h
index 843b2f2..9f6ca6e 100644
--- a/fs_mgr/liblp/reader.h
+++ b/fs_mgr/liblp/reader.h
@@ -26,11 +26,16 @@
 namespace android {
 namespace fs_mgr {
 
-std::unique_ptr<LpMetadata> ReadMetadata(int fd, uint32_t slot_number);
+// Parse an LpMetadataGeometry from a buffer. The buffer must be at least
+// LP_METADATA_GEOMETRY_SIZE bytes in size.
+bool ParseGeometry(const void* buffer, LpMetadataGeometry* geometry);
 
 // Helper functions for manually reading geometry and metadata.
+std::unique_ptr<LpMetadata> ReadMetadata(int fd, uint32_t slot_number);
+std::unique_ptr<LpMetadata> ParseMetadata(const LpMetadataGeometry& geometry, int fd);
+std::unique_ptr<LpMetadata> ParseMetadata(const LpMetadataGeometry& geometry, const void* buffer,
+                                          size_t size);
 bool ReadLogicalPartitionGeometry(int fd, LpMetadataGeometry* geometry);
-std::unique_ptr<LpMetadata> ParseMetadata(int fd);
 
 // These functions assume a valid geometry and slot number.
 std::unique_ptr<LpMetadata> ReadPrimaryMetadata(int fd, const LpMetadataGeometry& geometry,
diff --git a/fs_mgr/liblp/writer.cpp b/fs_mgr/liblp/writer.cpp
index fc9d83f..ad84b22 100644
--- a/fs_mgr/liblp/writer.cpp
+++ b/fs_mgr/liblp/writer.cpp
@@ -196,7 +196,7 @@
     return android::base::WriteFully(fd, blob.data(), blob.size());
 }
 
-bool FlashPartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number) {
+bool FlashPartitionTable(int fd, const LpMetadata& metadata) {
     // Before writing geometry and/or logical partition tables, perform some
     // basic checks that the geometry and tables are coherent, and will fit
     // on the given block device.
@@ -224,8 +224,11 @@
         return false;
     }
 
-    // Write metadata to the correct slot, now that geometry is in place.
-    return WriteMetadata(fd, metadata.geometry, slot_number, metadata_blob, DefaultWriter);
+    bool ok = true;
+    for (size_t i = 0; i < metadata.geometry.metadata_slot_count; i++) {
+        ok &= WriteMetadata(fd, metadata.geometry, i, metadata_blob, DefaultWriter);
+    }
+    return ok;
 }
 
 static bool CompareMetadata(const LpMetadata& a, const LpMetadata& b) {
@@ -297,14 +300,13 @@
     return WriteMetadata(fd, geometry, slot_number, blob, writer);
 }
 
-bool FlashPartitionTable(const std::string& block_device, const LpMetadata& metadata,
-                         uint32_t slot_number) {
+bool FlashPartitionTable(const std::string& block_device, const LpMetadata& metadata) {
     android::base::unique_fd fd(open(block_device.c_str(), O_RDWR | O_SYNC));
     if (fd < 0) {
         PERROR << __PRETTY_FUNCTION__ << "open failed: " << block_device;
         return false;
     }
-    if (!FlashPartitionTable(fd, metadata, slot_number)) {
+    if (!FlashPartitionTable(fd, metadata)) {
         return false;
     }
     LWARN << "Flashed new logical partition geometry to " << block_device;
diff --git a/fs_mgr/liblp/writer.h b/fs_mgr/liblp/writer.h
index adbbebf..ab18d45 100644
--- a/fs_mgr/liblp/writer.h
+++ b/fs_mgr/liblp/writer.h
@@ -30,7 +30,7 @@
 
 // These variants are for testing only. The path-based functions should be used
 // for actual operation, so that open() is called with the correct flags.
-bool FlashPartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number);
+bool FlashPartitionTable(int fd, const LpMetadata& metadata);
 bool UpdatePartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number);
 
 bool UpdatePartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number,
diff --git a/logd/main.cpp b/logd/main.cpp
index b697d44..8c38d9a 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -104,7 +104,8 @@
         return -1;
     }
 
-    if (__android_logger_property_get_bool("ro.debuggable", BOOL_DEFAULT_FALSE) &&
+    if (!__android_logger_property_get_bool("ro.debuggable",
+                                            BOOL_DEFAULT_FALSE) &&
         prctl(PR_SET_DUMPABLE, 0) == -1) {
         android::prdebug("failed to clear PR_SET_DUMPABLE");
         return -1;