Loading fastboot/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -196,6 +196,7 @@ cc_binary { "libfastbootshim", "libsnapshot_cow", "liblz4", "libzstd", "libsnapshot_nobinder", "update_metadata-protos", "liburing", Loading fs_mgr/libsnapshot/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -163,6 +163,7 @@ cc_defaults { "libbrotli", "libz", "liblz4", "libzstd", ], export_include_dirs: ["include"], } Loading fs_mgr/libsnapshot/include/libsnapshot/cow_format.h +2 −1 Original line number Diff line number Diff line Loading @@ -157,7 +157,8 @@ enum CowCompressionAlgorithm : uint8_t { kCowCompressNone = 0, kCowCompressGz = 1, kCowCompressBrotli = 2, kCowCompressLz4 = 3 kCowCompressLz4 = 3, kCowCompressZstd = 4, }; static constexpr uint8_t kCowReadAheadNotStarted = 0; Loading fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp +20 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include <libsnapshot/cow_writer.h> #include <lz4.h> #include <zlib.h> #include <zstd.h> namespace android { namespace snapshot { Loading @@ -40,6 +41,8 @@ std::optional<CowCompressionAlgorithm> CompressionAlgorithmFromString(std::strin return {kCowCompressBrotli}; } else if (name == "lz4") { return {kCowCompressLz4}; } else if (name == "zstd") { return {kCowCompressZstd}; } else if (name == "none" || name.empty()) { return {kCowCompressNone}; } else { Loading Loading @@ -112,6 +115,23 @@ std::basic_string<uint8_t> CompressWorker::Compress(CowCompressionAlgorithm comp } return buffer; } case kCowCompressZstd: { std::basic_string<uint8_t> buffer(ZSTD_compressBound(length), '\0'); const auto compressed_size = ZSTD_compress(buffer.data(), buffer.size(), data, length, 0); if (compressed_size <= 0) { LOG(ERROR) << "ZSTD compression failed " << compressed_size; return {}; } // Don't run compression if the compressed output is larger if (compressed_size >= length) { buffer.resize(length); memcpy(buffer.data(), data, length); } else { buffer.resize(compressed_size); } return buffer; } default: LOG(ERROR) << "unhandled compression type: " << compression; break; Loading fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.cpp +50 −0 Original line number Diff line number Diff line Loading @@ -17,12 +17,15 @@ #include "cow_decompress.h" #include <array> #include <cstring> #include <utility> #include <vector> #include <android-base/logging.h> #include <brotli/decode.h> #include <lz4.h> #include <zlib.h> #include <zstd.h> namespace android { namespace snapshot { Loading Loading @@ -336,9 +339,56 @@ class Lz4Decompressor final : public IDecompressor { } }; class ZstdDecompressor final : public IDecompressor { public: ssize_t Decompress(void* buffer, size_t buffer_size, size_t decompressed_size, size_t ignore_bytes = 0) override { if (buffer_size < decompressed_size - ignore_bytes) { LOG(INFO) << "buffer size " << buffer_size << " is not large enough to hold decompressed data. Decompressed size " << decompressed_size << ", ignore_bytes " << ignore_bytes; return -1; } if (ignore_bytes == 0) { if (!Decompress(buffer, decompressed_size)) { return -1; } return decompressed_size; } std::vector<unsigned char> ignore_buf(decompressed_size); if (!Decompress(buffer, decompressed_size)) { return -1; } memcpy(buffer, ignore_buf.data() + ignore_bytes, buffer_size); return decompressed_size; } bool Decompress(void* output_buffer, const size_t output_size) { std::string input_buffer; input_buffer.resize(stream_->Size()); size_t bytes_read = stream_->Read(input_buffer.data(), input_buffer.size()); if (bytes_read != input_buffer.size()) { LOG(ERROR) << "Failed to read all input at once. Expected: " << input_buffer.size() << " actual: " << bytes_read; return false; } const auto bytes_decompressed = ZSTD_decompress(output_buffer, output_size, input_buffer.data(), input_buffer.size()); if (bytes_decompressed != output_size) { LOG(ERROR) << "Failed to decompress ZSTD block, expected output size: " << output_size << ", actual: " << bytes_decompressed; return false; } return true; } }; std::unique_ptr<IDecompressor> IDecompressor::Lz4() { return std::make_unique<Lz4Decompressor>(); } std::unique_ptr<IDecompressor> IDecompressor::Zstd() { return std::make_unique<ZstdDecompressor>(); } } // namespace snapshot } // namespace android Loading
fastboot/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -196,6 +196,7 @@ cc_binary { "libfastbootshim", "libsnapshot_cow", "liblz4", "libzstd", "libsnapshot_nobinder", "update_metadata-protos", "liburing", Loading
fs_mgr/libsnapshot/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -163,6 +163,7 @@ cc_defaults { "libbrotli", "libz", "liblz4", "libzstd", ], export_include_dirs: ["include"], } Loading
fs_mgr/libsnapshot/include/libsnapshot/cow_format.h +2 −1 Original line number Diff line number Diff line Loading @@ -157,7 +157,8 @@ enum CowCompressionAlgorithm : uint8_t { kCowCompressNone = 0, kCowCompressGz = 1, kCowCompressBrotli = 2, kCowCompressLz4 = 3 kCowCompressLz4 = 3, kCowCompressZstd = 4, }; static constexpr uint8_t kCowReadAheadNotStarted = 0; Loading
fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp +20 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include <libsnapshot/cow_writer.h> #include <lz4.h> #include <zlib.h> #include <zstd.h> namespace android { namespace snapshot { Loading @@ -40,6 +41,8 @@ std::optional<CowCompressionAlgorithm> CompressionAlgorithmFromString(std::strin return {kCowCompressBrotli}; } else if (name == "lz4") { return {kCowCompressLz4}; } else if (name == "zstd") { return {kCowCompressZstd}; } else if (name == "none" || name.empty()) { return {kCowCompressNone}; } else { Loading Loading @@ -112,6 +115,23 @@ std::basic_string<uint8_t> CompressWorker::Compress(CowCompressionAlgorithm comp } return buffer; } case kCowCompressZstd: { std::basic_string<uint8_t> buffer(ZSTD_compressBound(length), '\0'); const auto compressed_size = ZSTD_compress(buffer.data(), buffer.size(), data, length, 0); if (compressed_size <= 0) { LOG(ERROR) << "ZSTD compression failed " << compressed_size; return {}; } // Don't run compression if the compressed output is larger if (compressed_size >= length) { buffer.resize(length); memcpy(buffer.data(), data, length); } else { buffer.resize(compressed_size); } return buffer; } default: LOG(ERROR) << "unhandled compression type: " << compression; break; Loading
fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.cpp +50 −0 Original line number Diff line number Diff line Loading @@ -17,12 +17,15 @@ #include "cow_decompress.h" #include <array> #include <cstring> #include <utility> #include <vector> #include <android-base/logging.h> #include <brotli/decode.h> #include <lz4.h> #include <zlib.h> #include <zstd.h> namespace android { namespace snapshot { Loading Loading @@ -336,9 +339,56 @@ class Lz4Decompressor final : public IDecompressor { } }; class ZstdDecompressor final : public IDecompressor { public: ssize_t Decompress(void* buffer, size_t buffer_size, size_t decompressed_size, size_t ignore_bytes = 0) override { if (buffer_size < decompressed_size - ignore_bytes) { LOG(INFO) << "buffer size " << buffer_size << " is not large enough to hold decompressed data. Decompressed size " << decompressed_size << ", ignore_bytes " << ignore_bytes; return -1; } if (ignore_bytes == 0) { if (!Decompress(buffer, decompressed_size)) { return -1; } return decompressed_size; } std::vector<unsigned char> ignore_buf(decompressed_size); if (!Decompress(buffer, decompressed_size)) { return -1; } memcpy(buffer, ignore_buf.data() + ignore_bytes, buffer_size); return decompressed_size; } bool Decompress(void* output_buffer, const size_t output_size) { std::string input_buffer; input_buffer.resize(stream_->Size()); size_t bytes_read = stream_->Read(input_buffer.data(), input_buffer.size()); if (bytes_read != input_buffer.size()) { LOG(ERROR) << "Failed to read all input at once. Expected: " << input_buffer.size() << " actual: " << bytes_read; return false; } const auto bytes_decompressed = ZSTD_decompress(output_buffer, output_size, input_buffer.data(), input_buffer.size()); if (bytes_decompressed != output_size) { LOG(ERROR) << "Failed to decompress ZSTD block, expected output size: " << output_size << ", actual: " << bytes_decompressed; return false; } return true; } }; std::unique_ptr<IDecompressor> IDecompressor::Lz4() { return std::make_unique<Lz4Decompressor>(); } std::unique_ptr<IDecompressor> IDecompressor::Zstd() { return std::make_unique<ZstdDecompressor>(); } } // namespace snapshot } // namespace android