liblp: Refactor ParseMetadata to read from non-descriptors.
This is in preparation for "fastboot flash super", where we want to
verify the validity of a super image before writing it. To do so, we
need to parse the image from the download buffer, and it is useful to do
this from memory rather than a file descriptor.
Bug: 78793464
Test: liblp_test gtest
Change-Id: I7fb1ef4fdf2e8f1d93aea38f75626157fcb4bfc1
diff --git a/fs_mgr/liblp/reader.cpp b/fs_mgr/liblp/reader.cpp
index b7074d8..d57af3f 100644
--- a/fs_mgr/liblp/reader.cpp
+++ b/fs_mgr/liblp/reader.cpp
@@ -30,6 +30,24 @@
namespace android {
namespace fs_mgr {
+// 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_;
+};
+
// 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) {
@@ -171,10 +189,11 @@
// Parse and validate all metadata at the current position in the given file
// descriptor.
-std::unique_ptr<LpMetadata> ParseMetadata(const LpMetadataGeometry& geometry, 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;
}
@@ -192,7 +211,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;
}
@@ -235,6 +254,11 @@
return metadata;
}
+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);