libsnapshot: Fix CowWriter::Finalize() not restoring footer correctly.

Bug: 173432386
Test: cow_api_test
Change-Id: If1b856fcdcd6b6ded5e00342037308c6b35d6fc0
This commit is contained in:
David Anderson 2021-03-11 16:14:30 -08:00
parent d5bd5437b0
commit bf3020b749
3 changed files with 28 additions and 2 deletions

View File

@ -757,6 +757,30 @@ TEST_F(CowTest, ClusterAppendTest) {
ASSERT_TRUE(iter->Done()); ASSERT_TRUE(iter->Done());
} }
TEST_F(CowTest, AppendAfterFinalize) {
CowOptions options;
options.cluster_ops = 0;
auto writer = std::make_unique<CowWriter>(options);
ASSERT_TRUE(writer->Initialize(cow_->fd));
std::string data = "This is some data, believe it";
data.resize(options.block_size, '\0');
ASSERT_TRUE(writer->AddRawBlocks(50, data.data(), data.size()));
ASSERT_TRUE(writer->AddLabel(3));
ASSERT_TRUE(writer->Finalize());
std::string data2 = "More data!";
data2.resize(options.block_size, '\0');
ASSERT_TRUE(writer->AddRawBlocks(51, data2.data(), data2.size()));
ASSERT_TRUE(writer->Finalize());
ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);
// COW should be valid.
CowReader reader;
ASSERT_TRUE(reader.Parse(cow_->fd));
}
} // namespace snapshot } // namespace snapshot
} // namespace android } // namespace android

View File

@ -229,7 +229,8 @@ bool CowReader::ParseOps(std::optional<uint64_t> label) {
if (footer_) { if (footer_) {
if (ops_buffer->size() != footer_->op.num_ops) { if (ops_buffer->size() != footer_->op.num_ops) {
LOG(ERROR) << "num ops does not match"; LOG(ERROR) << "num ops does not match, expected " << footer_->op.num_ops << ", found "
<< ops_buffer->size();
return false; return false;
} }
if (ops_buffer->size() * sizeof(CowOperation) != footer_->op.ops_size) { if (ops_buffer->size() * sizeof(CowOperation) != footer_->op.ops_size) {

View File

@ -376,6 +376,7 @@ bool CowWriter::Finalize() {
auto continue_data_pos = next_data_pos_; auto continue_data_pos = next_data_pos_;
auto continue_op_pos = next_op_pos_; auto continue_op_pos = next_op_pos_;
auto continue_size = ops_.size(); auto continue_size = ops_.size();
auto continue_num_ops = footer_.op.num_ops;
bool extra_cluster = false; bool extra_cluster = false;
// Footer should be at the end of a file, so if there is data after the current block, end it // Footer should be at the end of a file, so if there is data after the current block, end it
@ -408,9 +409,9 @@ bool CowWriter::Finalize() {
current_data_size_ = continue_data_size; current_data_size_ = continue_data_size;
next_data_pos_ = continue_data_pos; next_data_pos_ = continue_data_pos;
next_op_pos_ = continue_op_pos; next_op_pos_ = continue_op_pos;
footer_.op.num_ops = continue_num_ops;
ops_.resize(continue_size); ops_.resize(continue_size);
} }
return Sync(); return Sync();
} }