Loading fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h +5 −2 Original line number Diff line number Diff line Loading @@ -172,7 +172,7 @@ class CowReader final : public ICowReader { android::base::unique_fd owned_fd_; android::base::borrowed_fd fd_; CowHeader header_; CowHeaderV3 header_; std::optional<CowFooter> footer_; uint64_t fd_size_; std::optional<uint64_t> last_label_; Loading @@ -188,7 +188,10 @@ class CowReader final : public ICowReader { uint8_t compression_type_ = kCowCompressNone; }; bool ReadCowHeader(android::base::borrowed_fd fd, CowHeader* header); // Though this function takes in a CowHeaderV3, the struct could be populated as a v1/v2 CowHeader. // The extra fields will just be filled as 0. V3 header is strictly a superset of v1/v2 header and // contains all of the latter's field bool ReadCowHeader(android::base::borrowed_fd fd, CowHeaderV3* header); } // namespace snapshot } // namespace android fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp +4 −3 Original line number Diff line number Diff line Loading @@ -28,12 +28,13 @@ #include <zlib.h> #include "cow_decompress.h" #include "libsnapshot/cow_format.h" #include "parser_v2.h" namespace android { namespace snapshot { bool ReadCowHeader(android::base::borrowed_fd fd, CowHeader* header) { bool ReadCowHeader(android::base::borrowed_fd fd, CowHeaderV3* header) { if (lseek(fd.get(), 0, SEEK_SET) < 0) { PLOG(ERROR) << "lseek header failed"; return false; Loading @@ -49,9 +50,9 @@ bool ReadCowHeader(android::base::borrowed_fd fd, CowHeader* header) { << "Expected: " << kCowMagicNumber; return false; } if (header->prefix.header_size > sizeof(CowHeader)) { if (header->prefix.header_size > sizeof(CowHeaderV3)) { LOG(ERROR) << "Unknown CowHeader size (got " << header->prefix.header_size << " bytes, expected at most " << sizeof(CowHeader) << " bytes)"; << " bytes, expected at most " << sizeof(CowHeaderV3) << " bytes)"; return false; } Loading fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -90,7 +90,7 @@ static bool ShowRawOpStreamV2(borrowed_fd fd, const CowHeader& header) { } static bool ShowRawOpStream(borrowed_fd fd) { CowHeader header; CowHeaderV3 header; if (!ReadCowHeader(fd, &header)) { LOG(ERROR) << "parse header failed"; return false; Loading fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp +24 −0 Original line number Diff line number Diff line Loading @@ -26,7 +26,9 @@ #include <libsnapshot/cow_writer.h> #include "cow_decompress.h" #include "libsnapshot/cow_format.h" #include "writer_v2.h" #include "writer_v3.h" using android::base::unique_fd; using testing::AssertionFailure; using testing::AssertionResult; Loading @@ -49,5 +51,27 @@ class CowOperationV3Test : public ::testing::Test { std::unique_ptr<TemporaryFile> cow_; }; TEST_F(CowOperationV3Test, CowHeaderV2Test) { CowOptions options; options.cluster_ops = 5; options.num_merge_ops = 1; options.block_size = 4096; std::string data = "This is some data, believe it"; data.resize(options.block_size, '\0'); auto writer_v2 = std::make_unique<CowWriterV2>(options, GetCowFd()); ASSERT_TRUE(writer_v2->Initialize()); ASSERT_TRUE(writer_v2->Finalize()); CowReader reader; ASSERT_TRUE(reader.Parse(cow_->fd)); const auto& header = reader.GetHeader(); ASSERT_EQ(header.prefix.magic, kCowMagicNumber); ASSERT_EQ(header.prefix.major_version, kCowVersionMajor); ASSERT_EQ(header.prefix.minor_version, kCowVersionMinor); ASSERT_EQ(header.block_size, options.block_size); ASSERT_EQ(header.cluster_ops, options.cluster_ops); } } // namespace snapshot } // namespace android No newline at end of file fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -269,9 +269,11 @@ bool CowWriterV2::OpenForWrite() { } bool CowWriterV2::OpenForAppend(uint64_t label) { if (!ReadCowHeader(fd_, &header_)) { CowHeaderV3 header_v3; if (!ReadCowHeader(fd_, &header_v3)) { return false; } header_ = header_v3; CowParserV2 parser; if (!parser.Parse(fd_, header_, {label})) { Loading Loading
fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h +5 −2 Original line number Diff line number Diff line Loading @@ -172,7 +172,7 @@ class CowReader final : public ICowReader { android::base::unique_fd owned_fd_; android::base::borrowed_fd fd_; CowHeader header_; CowHeaderV3 header_; std::optional<CowFooter> footer_; uint64_t fd_size_; std::optional<uint64_t> last_label_; Loading @@ -188,7 +188,10 @@ class CowReader final : public ICowReader { uint8_t compression_type_ = kCowCompressNone; }; bool ReadCowHeader(android::base::borrowed_fd fd, CowHeader* header); // Though this function takes in a CowHeaderV3, the struct could be populated as a v1/v2 CowHeader. // The extra fields will just be filled as 0. V3 header is strictly a superset of v1/v2 header and // contains all of the latter's field bool ReadCowHeader(android::base::borrowed_fd fd, CowHeaderV3* header); } // namespace snapshot } // namespace android
fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp +4 −3 Original line number Diff line number Diff line Loading @@ -28,12 +28,13 @@ #include <zlib.h> #include "cow_decompress.h" #include "libsnapshot/cow_format.h" #include "parser_v2.h" namespace android { namespace snapshot { bool ReadCowHeader(android::base::borrowed_fd fd, CowHeader* header) { bool ReadCowHeader(android::base::borrowed_fd fd, CowHeaderV3* header) { if (lseek(fd.get(), 0, SEEK_SET) < 0) { PLOG(ERROR) << "lseek header failed"; return false; Loading @@ -49,9 +50,9 @@ bool ReadCowHeader(android::base::borrowed_fd fd, CowHeader* header) { << "Expected: " << kCowMagicNumber; return false; } if (header->prefix.header_size > sizeof(CowHeader)) { if (header->prefix.header_size > sizeof(CowHeaderV3)) { LOG(ERROR) << "Unknown CowHeader size (got " << header->prefix.header_size << " bytes, expected at most " << sizeof(CowHeader) << " bytes)"; << " bytes, expected at most " << sizeof(CowHeaderV3) << " bytes)"; return false; } Loading
fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -90,7 +90,7 @@ static bool ShowRawOpStreamV2(borrowed_fd fd, const CowHeader& header) { } static bool ShowRawOpStream(borrowed_fd fd) { CowHeader header; CowHeaderV3 header; if (!ReadCowHeader(fd, &header)) { LOG(ERROR) << "parse header failed"; return false; Loading
fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp +24 −0 Original line number Diff line number Diff line Loading @@ -26,7 +26,9 @@ #include <libsnapshot/cow_writer.h> #include "cow_decompress.h" #include "libsnapshot/cow_format.h" #include "writer_v2.h" #include "writer_v3.h" using android::base::unique_fd; using testing::AssertionFailure; using testing::AssertionResult; Loading @@ -49,5 +51,27 @@ class CowOperationV3Test : public ::testing::Test { std::unique_ptr<TemporaryFile> cow_; }; TEST_F(CowOperationV3Test, CowHeaderV2Test) { CowOptions options; options.cluster_ops = 5; options.num_merge_ops = 1; options.block_size = 4096; std::string data = "This is some data, believe it"; data.resize(options.block_size, '\0'); auto writer_v2 = std::make_unique<CowWriterV2>(options, GetCowFd()); ASSERT_TRUE(writer_v2->Initialize()); ASSERT_TRUE(writer_v2->Finalize()); CowReader reader; ASSERT_TRUE(reader.Parse(cow_->fd)); const auto& header = reader.GetHeader(); ASSERT_EQ(header.prefix.magic, kCowMagicNumber); ASSERT_EQ(header.prefix.major_version, kCowVersionMajor); ASSERT_EQ(header.prefix.minor_version, kCowVersionMinor); ASSERT_EQ(header.block_size, options.block_size); ASSERT_EQ(header.cluster_ops, options.cluster_ops); } } // namespace snapshot } // namespace android No newline at end of file
fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -269,9 +269,11 @@ bool CowWriterV2::OpenForWrite() { } bool CowWriterV2::OpenForAppend(uint64_t label) { if (!ReadCowHeader(fd_, &header_)) { CowHeaderV3 header_v3; if (!ReadCowHeader(fd_, &header_v3)) { return false; } header_ = header_v3; CowParserV2 parser; if (!parser.Parse(fd_, header_, {label})) { Loading