Add FileDescriptorPtr interface to verity writer
In VABC, read/write of target partition is no longer done via unix file
descriptor. Instead it's done via CowWriter and FiledescriptorPtr.
We need abstraction for verity writer.
Test: treehugger
Change-Id: Id638b4e5a2cea4ab97927a6e7089170a3e257dee
diff --git a/payload_consumer/verity_writer_android.cc b/payload_consumer/verity_writer_android.cc
index d5437b6..864d9a1 100644
--- a/payload_consumer/verity_writer_android.cc
+++ b/payload_consumer/verity_writer_android.cc
@@ -29,6 +29,7 @@
}
#include "update_engine/common/utils.h"
+#include "update_engine/payload_consumer/file_descriptor.h"
namespace chromeos_update_engine {
@@ -39,7 +40,16 @@
} // namespace verity_writer
bool VerityWriterAndroid::Init(const InstallPlan::Partition& partition) {
+ auto read_fd = FileDescriptorPtr(new EintrSafeFileDescriptor());
+ TEST_AND_RETURN_FALSE(read_fd->Open(partition.target_path.c_str(), O_RDWR));
+ return Init(partition, read_fd, read_fd);
+}
+bool VerityWriterAndroid::Init(const InstallPlan::Partition& partition,
+ FileDescriptorPtr read_fd,
+ FileDescriptorPtr write_fd) {
partition_ = &partition;
+ read_fd_ = read_fd;
+ write_fd_ = write_fd;
if (partition_->hash_tree_size != 0 || partition_->fec_size != 0) {
utils::SetBlockDeviceReadOnly(partition_->target_path, false);
@@ -82,18 +92,18 @@
if (end_offset == hash_tree_data_end) {
// All hash tree data blocks has been hashed, write hash tree to disk.
- int fd = HANDLE_EINTR(open(partition_->target_path.c_str(), O_WRONLY));
- if (fd < 0) {
- PLOG(ERROR) << "Failed to open " << partition_->target_path
- << " to write hash tree.";
- return false;
- }
- ScopedFdCloser fd_closer(&fd);
-
LOG(INFO) << "Writing verity hash tree to " << partition_->target_path;
TEST_AND_RETURN_FALSE(hash_tree_builder_->BuildHashTree());
- TEST_AND_RETURN_FALSE(hash_tree_builder_->WriteHashTreeToFd(
- fd, partition_->hash_tree_offset));
+ TEST_AND_RETURN_FALSE_ERRNO(
+ write_fd_->Seek(partition_->hash_tree_offset, SEEK_SET));
+ auto success = hash_tree_builder_->WriteHashTree(
+ [write_fd_(this->write_fd_)](auto data, auto size) {
+ return utils::WriteAll(write_fd_, data, size);
+ });
+ // hashtree builder already prints error messages.
+ if (!success) {
+ return false;
+ }
hash_tree_builder_.reset();
}
}
@@ -103,7 +113,8 @@
partition_->fec_data_offset + partition_->fec_data_size;
if (offset < fec_data_end && offset + size >= fec_data_end) {
LOG(INFO) << "Writing verity FEC to " << partition_->target_path;
- TEST_AND_RETURN_FALSE(EncodeFEC(partition_->target_path,
+ TEST_AND_RETURN_FALSE(EncodeFEC(read_fd_,
+ write_fd_,
partition_->fec_data_offset,
partition_->fec_data_size,
partition_->fec_offset,
@@ -116,7 +127,8 @@
return true;
}
-bool VerityWriterAndroid::EncodeFEC(const std::string& path,
+bool VerityWriterAndroid::EncodeFEC(FileDescriptorPtr read_fd,
+ FileDescriptorPtr write_fd,
uint64_t data_offset,
uint64_t data_size,
uint64_t fec_offset,
@@ -135,13 +147,6 @@
init_rs_char(FEC_PARAMS(fec_roots)), &free_rs_char);
TEST_AND_RETURN_FALSE(rs_char != nullptr);
- int fd = HANDLE_EINTR(open(path.c_str(), verify_mode ? O_RDONLY : O_RDWR));
- if (fd < 0) {
- PLOG(ERROR) << "Failed to open " << path << " to write FEC.";
- return false;
- }
- ScopedFdCloser fd_closer(&fd);
-
for (size_t i = 0; i < rounds; i++) {
// Encodes |block_size| number of rs blocks each round so that we can read
// one block each time instead of 1 byte to increase random read
@@ -154,13 +159,13 @@
// Don't read past |data_size|, treat them as 0.
if (offset < data_size) {
ssize_t bytes_read = 0;
- TEST_AND_RETURN_FALSE(utils::PReadAll(fd,
+ TEST_AND_RETURN_FALSE(utils::PReadAll(read_fd,
buffer.data(),
buffer.size(),
data_offset + offset,
&bytes_read));
- TEST_AND_RETURN_FALSE(bytes_read ==
- static_cast<ssize_t>(buffer.size()));
+ TEST_AND_RETURN_FALSE(bytes_read >= 0);
+ TEST_AND_RETURN_FALSE(static_cast<size_t>(bytes_read) == buffer.size());
}
for (size_t k = 0; k < buffer.size(); k++) {
rs_blocks[k * rs_n + j] = buffer[k];
@@ -179,17 +184,42 @@
brillo::Blob fec_read(fec.size());
ssize_t bytes_read = 0;
TEST_AND_RETURN_FALSE(utils::PReadAll(
- fd, fec_read.data(), fec_read.size(), fec_offset, &bytes_read));
- TEST_AND_RETURN_FALSE(bytes_read ==
- static_cast<ssize_t>(fec_read.size()));
+ read_fd, fec_read.data(), fec_read.size(), fec_offset, &bytes_read));
+ TEST_AND_RETURN_FALSE(bytes_read >= 0);
+ TEST_AND_RETURN_FALSE(static_cast<size_t>(bytes_read) == fec_read.size());
TEST_AND_RETURN_FALSE(fec == fec_read);
} else {
- TEST_AND_RETURN_FALSE(
- utils::PWriteAll(fd, fec.data(), fec.size(), fec_offset));
+ CHECK(write_fd);
+ if (!utils::PWriteAll(write_fd, fec.data(), fec.size(), fec_offset)) {
+ PLOG(ERROR) << "EncodeFEC write() failed";
+ return false;
+ }
}
fec_offset += fec.size();
}
return true;
}
+
+bool VerityWriterAndroid::EncodeFEC(const std::string& path,
+ uint64_t data_offset,
+ uint64_t data_size,
+ uint64_t fec_offset,
+ uint64_t fec_size,
+ uint32_t fec_roots,
+ uint32_t block_size,
+ bool verify_mode) {
+ FileDescriptorPtr fd(new EintrSafeFileDescriptor());
+ TEST_AND_RETURN_FALSE(
+ fd->Open(path.c_str(), verify_mode ? O_RDONLY : O_RDWR));
+ return EncodeFEC(fd,
+ fd,
+ data_offset,
+ data_size,
+ fec_offset,
+ fec_size,
+ fec_roots,
+ block_size,
+ verify_mode);
+}
} // namespace chromeos_update_engine
diff --git a/payload_consumer/verity_writer_android.h b/payload_consumer/verity_writer_android.h
index 05a5856..7dfac0f 100644
--- a/payload_consumer/verity_writer_android.h
+++ b/payload_consumer/verity_writer_android.h
@@ -22,6 +22,7 @@
#include <verity/hash_tree_builder.h>
+#include "payload_consumer/file_descriptor.h"
#include "update_engine/payload_consumer/verity_writer_interface.h"
namespace chromeos_update_engine {
@@ -31,7 +32,10 @@
VerityWriterAndroid() = default;
~VerityWriterAndroid() override = default;
- bool Init(const InstallPlan::Partition& partition) override;
+ bool Init(const InstallPlan::Partition& partition,
+ FileDescriptorPtr read_fd,
+ FileDescriptorPtr write_fd) override;
+ bool Init(const InstallPlan::Partition& partition);
bool Update(uint64_t offset, const uint8_t* buffer, size_t size) override;
// Read [data_offset : data_offset + data_size) from |path| and encode FEC
@@ -40,6 +44,15 @@
// in each Update() like hash tree, because for every rs block, its data are
// spreaded across entire |data_size|, unless we can cache all data in
// memory, we have to re-read them from disk.
+ static bool EncodeFEC(FileDescriptorPtr read_fd,
+ FileDescriptorPtr write_fd,
+ uint64_t data_offset,
+ uint64_t data_size,
+ uint64_t fec_offset,
+ uint64_t fec_size,
+ uint32_t fec_roots,
+ uint32_t block_size,
+ bool verify_mode);
static bool EncodeFEC(const std::string& path,
uint64_t data_offset,
uint64_t data_size,
@@ -52,6 +65,8 @@
private:
const InstallPlan::Partition* partition_ = nullptr;
+ FileDescriptorPtr read_fd_;
+ FileDescriptorPtr write_fd_;
std::unique_ptr<HashTreeBuilder> hash_tree_builder_;
DISALLOW_COPY_AND_ASSIGN(VerityWriterAndroid);
diff --git a/payload_consumer/verity_writer_interface.h b/payload_consumer/verity_writer_interface.h
index a3ecef3..db7988e 100644
--- a/payload_consumer/verity_writer_interface.h
+++ b/payload_consumer/verity_writer_interface.h
@@ -22,6 +22,7 @@
#include <base/macros.h>
+#include "payload_consumer/file_descriptor.h"
#include "update_engine/payload_consumer/install_plan.h"
namespace chromeos_update_engine {
@@ -30,6 +31,9 @@
public:
virtual ~VerityWriterInterface() = default;
+ virtual bool Init(const InstallPlan::Partition& partition,
+ FileDescriptorPtr read_fd,
+ FileDescriptorPtr write_fd) = 0;
virtual bool Init(const InstallPlan::Partition& partition) = 0;
// Update partition data at [offset : offset + size) stored in |buffer|.
// Data not in |hash_tree_data_extent| or |fec_data_extent| is ignored.
diff --git a/payload_consumer/verity_writer_stub.cc b/payload_consumer/verity_writer_stub.cc
index a0e2467..314ec7e 100644
--- a/payload_consumer/verity_writer_stub.cc
+++ b/payload_consumer/verity_writer_stub.cc
@@ -26,7 +26,9 @@
}
} // namespace verity_writer
-bool VerityWriterStub::Init(const InstallPlan::Partition& partition) {
+bool VerityWriterStub::Init(const InstallPlan::Partition& partition,
+ FileDescriptorPtr read_fd,
+ FileDescriptorPtr write_fd) {
return partition.hash_tree_size == 0 && partition.fec_size == 0;
}
diff --git a/payload_consumer/verity_writer_stub.h b/payload_consumer/verity_writer_stub.h
index ea5e574..f8d68ca 100644
--- a/payload_consumer/verity_writer_stub.h
+++ b/payload_consumer/verity_writer_stub.h
@@ -26,7 +26,9 @@
VerityWriterStub() = default;
~VerityWriterStub() override = default;
- bool Init(const InstallPlan::Partition& partition) override;
+ bool Init(const InstallPlan::Partition& partition,
+ FileDescriptorPtr read_fd,
+ FileDescriptorPtr write_fd) override;
bool Update(uint64_t offset, const uint8_t* buffer, size_t size) override;
private: