Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bf3020b7 authored by David Anderson's avatar David Anderson
Browse files

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

Bug: 173432386
Test: cow_api_test
Change-Id: If1b856fcdcd6b6ded5e00342037308c6b35d6fc0
parent d5bd5437
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -757,6 +757,30 @@ TEST_F(CowTest, ClusterAppendTest) {
    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 android

+2 −1
Original line number Diff line number Diff line
@@ -229,7 +229,8 @@ bool CowReader::ParseOps(std::optional<uint64_t> label) {

    if (footer_) {
        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;
        }
        if (ops_buffer->size() * sizeof(CowOperation) != footer_->op.ops_size) {
+2 −1
Original line number Diff line number Diff line
@@ -376,6 +376,7 @@ bool CowWriter::Finalize() {
    auto continue_data_pos = next_data_pos_;
    auto continue_op_pos = next_op_pos_;
    auto continue_size = ops_.size();
    auto continue_num_ops = footer_.op.num_ops;
    bool extra_cluster = false;

    // 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;
        next_data_pos_ = continue_data_pos;
        next_op_pos_ = continue_op_pos;
        footer_.op.num_ops = continue_num_ops;
        ops_.resize(continue_size);
    }

    return Sync();
}