summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2018-02-18 08:27:17 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2018-02-18 08:27:17 +0000
commitf0c8211af44d092cf6cc816b1e9af72f14fe80f6 (patch)
tree11699d8101fe082b541a365de69b62f934a2fe47
parent335d9aebe5923bdcb06e552257a91a9aa8f3c543 (diff)
parent359aa079d3dcff5f4aee11faf5a74239d0cbe64a (diff)
downloadbsdiff-pie-cts-release.tar.gz
Snap for 4610834 from 359aa079d3dcff5f4aee11faf5a74239d0cbe64a to pi-releaseandroid-wear-9.0.0_r9android-wear-9.0.0_r8android-wear-9.0.0_r7android-wear-9.0.0_r6android-wear-9.0.0_r5android-wear-9.0.0_r4android-wear-9.0.0_r34android-wear-9.0.0_r33android-wear-9.0.0_r32android-wear-9.0.0_r31android-wear-9.0.0_r30android-wear-9.0.0_r3android-wear-9.0.0_r29android-wear-9.0.0_r28android-wear-9.0.0_r27android-wear-9.0.0_r26android-wear-9.0.0_r25android-wear-9.0.0_r24android-wear-9.0.0_r23android-wear-9.0.0_r22android-wear-9.0.0_r21android-wear-9.0.0_r20android-wear-9.0.0_r2android-wear-9.0.0_r19android-wear-9.0.0_r18android-wear-9.0.0_r17android-wear-9.0.0_r16android-wear-9.0.0_r15android-wear-9.0.0_r14android-wear-9.0.0_r13android-wear-9.0.0_r12android-wear-9.0.0_r11android-wear-9.0.0_r10android-wear-9.0.0_r1android-vts-9.0_r9android-vts-9.0_r8android-vts-9.0_r7android-vts-9.0_r6android-vts-9.0_r5android-vts-9.0_r4android-vts-9.0_r19android-vts-9.0_r18android-vts-9.0_r17android-vts-9.0_r16android-vts-9.0_r15android-vts-9.0_r14android-vts-9.0_r13android-vts-9.0_r12android-vts-9.0_r11android-vts-9.0_r10android-security-9.0.0_r76android-security-9.0.0_r75android-security-9.0.0_r74android-security-9.0.0_r73android-security-9.0.0_r72android-security-9.0.0_r71android-security-9.0.0_r70android-security-9.0.0_r69android-security-9.0.0_r68android-security-9.0.0_r67android-security-9.0.0_r66android-security-9.0.0_r65android-security-9.0.0_r64android-security-9.0.0_r63android-security-9.0.0_r62android-cts-9.0_r9android-cts-9.0_r8android-cts-9.0_r7android-cts-9.0_r6android-cts-9.0_r5android-cts-9.0_r4android-cts-9.0_r3android-cts-9.0_r20android-cts-9.0_r2android-cts-9.0_r19android-cts-9.0_r18android-cts-9.0_r17android-cts-9.0_r16android-cts-9.0_r15android-cts-9.0_r14android-cts-9.0_r13android-cts-9.0_r12android-cts-9.0_r11android-cts-9.0_r10android-cts-9.0_r1android-9.0.0_r9android-9.0.0_r8android-9.0.0_r7android-9.0.0_r61android-9.0.0_r60android-9.0.0_r6android-9.0.0_r59android-9.0.0_r58android-9.0.0_r57android-9.0.0_r56android-9.0.0_r55android-9.0.0_r54android-9.0.0_r53android-9.0.0_r52android-9.0.0_r51android-9.0.0_r50android-9.0.0_r5android-9.0.0_r49android-9.0.0_r48android-9.0.0_r3android-9.0.0_r2android-9.0.0_r18android-9.0.0_r17android-9.0.0_r10android-9.0.0_r1security-pi-releasepie-vts-releasepie-security-releasepie-s2-releasepie-release-2pie-releasepie-r2-s2-releasepie-r2-s1-releasepie-r2-releasepie-platform-releasepie-gsipie-cuttlefish-testingpie-cts-release
Change-Id: I6382adadb4487efe07d1b274f06a6d4fb7b41dda
-rw-r--r--bsdiff_arguments.cc30
-rw-r--r--bsdiff_arguments_unittest.cc3
-rw-r--r--bsdiff_main.cc35
-rw-r--r--endsley_patch_writer.cc45
-rw-r--r--endsley_patch_writer.h17
-rw-r--r--endsley_patch_writer_unittest.cc30
-rw-r--r--include/bsdiff/patch_writer_factory.h16
-rw-r--r--include/bsdiff/patch_writer_interface.h1
-rw-r--r--patch_writer_factory.cc11
-rw-r--r--utils.cc4
10 files changed, 161 insertions, 31 deletions
diff --git a/bsdiff_arguments.cc b/bsdiff_arguments.cc
index f56c186..ebcddf1 100644
--- a/bsdiff_arguments.cc
+++ b/bsdiff_arguments.cc
@@ -1,3 +1,7 @@
+// Copyright 2017 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
#include "bsdiff/bsdiff_arguments.h"
#include <getopt.h>
@@ -21,6 +25,7 @@ constexpr char kBrotliString[] = "brotli";
constexpr char kLegacyString[] = "legacy";
constexpr char kBsdf2String[] = "bsdf2";
constexpr char kBsdiff40String[] = "bsdiff40";
+constexpr char kEndsleyString[] = "endsley";
const struct option OPTIONS[] = {
{"format", required_argument, nullptr, 0},
@@ -37,16 +42,20 @@ const uint32_t kBrotliDefaultQuality = BROTLI_MAX_QUALITY;
namespace bsdiff {
bool BsdiffArguments::IsValid() const {
+ if (compressor_type_ == CompressorType::kBrotli &&
+ (compression_quality_ < BROTLI_MIN_QUALITY ||
+ compression_quality_ > BROTLI_MAX_QUALITY)) {
+ return false;
+ }
+
if (format_ == BsdiffFormat::kLegacy) {
- return (compressor_type_ == CompressorType::kBZ2);
+ return compressor_type_ == CompressorType::kBZ2;
} else if (format_ == BsdiffFormat::kBsdf2) {
- if (compressor_type_ == CompressorType::kBZ2) {
- return true;
- }
- if (compressor_type_ == CompressorType::kBrotli) {
- return (compression_quality_ >= BROTLI_MIN_QUALITY &&
- compression_quality_ <= BROTLI_MAX_QUALITY);
- }
+ return (compressor_type_ == CompressorType::kBZ2 ||
+ compressor_type_ == CompressorType::kBrotli);
+ } else if (format_ == BsdiffFormat::kEndsley) {
+ // All compression options are valid for this format.
+ return true;
}
return false;
}
@@ -83,7 +92,7 @@ bool BsdiffArguments::ParseCommandLine(int argc, char** argv) {
}
// If quality is uninitialized for brotli, set it to default value.
- if (format_ == BsdiffFormat::kBsdf2 &&
+ if (format_ != BsdiffFormat::kLegacy &&
compressor_type_ == CompressorType::kBrotli &&
compression_quality_ == -1) {
compression_quality_ = kBrotliDefaultQuality;
@@ -144,6 +153,9 @@ bool BsdiffArguments::ParseBsdiffFormat(const string& str,
} else if (format_string == kBsdf2String) {
*format = BsdiffFormat::kBsdf2;
return true;
+ } else if (format_string == kEndsleyString) {
+ *format = BsdiffFormat::kEndsley;
+ return true;
}
std::cerr << "Failed to parse bsdiff format in " << str << endl;
return false;
diff --git a/bsdiff_arguments_unittest.cc b/bsdiff_arguments_unittest.cc
index 3f061c9..412b8e9 100644
--- a/bsdiff_arguments_unittest.cc
+++ b/bsdiff_arguments_unittest.cc
@@ -32,6 +32,9 @@ TEST(BsdiffArgumentsTest, ParseBsdiffFormatTest) {
EXPECT_TRUE(BsdiffArguments::ParseBsdiffFormat("bsdiff40", &format));
EXPECT_EQ(BsdiffFormat::kLegacy, format);
+ EXPECT_TRUE(BsdiffArguments::ParseBsdiffFormat("endsley", &format));
+ EXPECT_EQ(BsdiffFormat::kEndsley, format);
+
EXPECT_FALSE(BsdiffArguments::ParseBsdiffFormat("Other", &format));
}
diff --git a/bsdiff_main.cc b/bsdiff_main.cc
index 6747055..bed38b6 100644
--- a/bsdiff_main.cc
+++ b/bsdiff_main.cc
@@ -74,12 +74,18 @@ int GenerateBsdiffFromFiles(const char* old_filename,
}
std::unique_ptr<bsdiff::PatchWriterInterface> patch_writer;
+ std::vector<uint8_t> raw_data;
+
if (arguments.format() == bsdiff::BsdiffFormat::kLegacy) {
patch_writer = bsdiff::CreateBsdiffPatchWriter(patch_filename);
} else if (arguments.format() == bsdiff::BsdiffFormat::kBsdf2) {
patch_writer = bsdiff::CreateBSDF2PatchWriter(
patch_filename, arguments.compressor_type(),
arguments.compression_quality());
+ } else if (arguments.format() == bsdiff::BsdiffFormat::kEndsley) {
+ patch_writer =
+ bsdiff::CreateEndsleyPatchWriter(&raw_data, arguments.compressor_type(),
+ arguments.compression_quality());
} else {
std::cerr << "unexpected bsdiff format." << std::endl;
return 1;
@@ -91,20 +97,33 @@ int GenerateBsdiffFromFiles(const char* old_filename,
munmap(old_buf, oldsize);
munmap(new_buf, newsize);
+ if (!ret && arguments.format() == bsdiff::BsdiffFormat::kEndsley) {
+ // Store the raw_data on disk.
+ FILE* fp = fopen(patch_filename, "wb");
+ if (!fp) {
+ perror("Opening the patch file");
+ return 1;
+ }
+ if (raw_data.size() != fwrite(raw_data.data(), 1, raw_data.size(), fp)) {
+ perror("Writing to the patch file");
+ ret = 1;
+ }
+ fclose(fp);
+ }
return ret;
}
void PrintUsage(const std::string& proc_name) {
std::cerr << "usage: " << proc_name
<< " [options] oldfile newfile patchfile\n";
- std::cerr << " --format <legacy|bsdiff40|bsdf2> The format of the bsdiff"
- " patch.\n"
- << " --minlen LEN The minimum match length required "
- "to consider a match in the algorithm.\n"
- << " --type <bz2|brotli> The algorithm to compress the "
- "patch, bsdf2 format only.\n"
- << " --quality Quality of the patch compression,"
- " brotli only.\n";
+ std::cerr << " --format <legacy|bsdiff40|bsdf2|endsley> The format of the"
+ " bsdiff patch.\n"
+ << " --minlen LEN The minimum match length "
+ "required to consider a match in the algorithm.\n"
+ << " --type <bz2|brotli|nocompression> The algorithm to compress "
+ "the patch, bsdf2 format only.\n"
+ << " --quality Quality of the patch "
+ "compression, brotli only.\n";
}
} // namespace
diff --git a/endsley_patch_writer.cc b/endsley_patch_writer.cc
index cb23f46..e40406d 100644
--- a/endsley_patch_writer.cc
+++ b/endsley_patch_writer.cc
@@ -8,6 +8,8 @@
#include <algorithm>
+#include "bsdiff/brotli_compressor.h"
+#include "bsdiff/bz2_compressor.h"
#include "bsdiff/logging.h"
namespace {
@@ -30,12 +32,30 @@ constexpr size_t kMinimumFlushSize = 1024 * 1024; // 1 MiB
namespace bsdiff {
bool EndsleyPatchWriter::Init(size_t new_size) {
- // The patch is uncompressed and it will need exactly:
- // new_size + 24 * len(control_entries) + sizeof(header)
- // We don't know the length of the control entries yet, but we can reserve
- // enough space to hold at least |new_size|.
- patch_->clear();
- patch_->reserve(new_size);
+ switch (compressor_type_) {
+ case CompressorType::kNoCompression:
+ // The patch is uncompressed and it will need exactly:
+ // new_size + 24 * len(control_entries) + sizeof(header)
+ // We don't know the length of the control entries yet, but we can reserve
+ // enough space to hold at least |new_size|.
+ patch_->clear();
+ patch_->reserve(new_size);
+ break;
+ case CompressorType::kBrotli:
+ compressor_.reset(new BrotliCompressor(quality_));
+ if (!compressor_) {
+ LOG(ERROR) << "Error creating brotli compressor.";
+ return false;
+ }
+ break;
+ case CompressorType::kBZ2:
+ compressor_.reset(new BZ2Compressor());
+ if (!compressor_) {
+ LOG(ERROR) << "Error creating BZ2 compressor.";
+ return false;
+ }
+ break;
+ }
// Header is the magic followed by the new length.
uint8_t header[24];
@@ -116,6 +136,13 @@ bool EndsleyPatchWriter::Close() {
LOG(ERROR) << "Pending data to diff/extra not flushed out on Close()";
return false;
}
+
+ if (compressor_) {
+ if (!compressor_->Finish())
+ return false;
+ *patch_ = compressor_->GetCompressedData();
+ }
+
return true;
}
@@ -129,7 +156,11 @@ void EndsleyPatchWriter::EmitControlEntry(const ControlEntry& entry) {
}
void EndsleyPatchWriter::EmitBuffer(const uint8_t* data, size_t size) {
- patch_->insert(patch_->end(), data, data + size);
+ if (compressor_) {
+ compressor_->Write(data, size);
+ } else {
+ patch_->insert(patch_->end(), data, data + size);
+ }
}
void EndsleyPatchWriter::Flush() {
diff --git a/endsley_patch_writer.h b/endsley_patch_writer.h
index 1840d8d..a3170f6 100644
--- a/endsley_patch_writer.h
+++ b/endsley_patch_writer.h
@@ -5,9 +5,12 @@
#ifndef _BSDIFF_ENDSLEY_PATCH_WRITER_H_
#define _BSDIFF_ENDSLEY_PATCH_WRITER_H_
+#include <memory>
#include <string>
#include <vector>
+#include "bsdiff/compressor_interface.h"
+#include "bsdiff/constants.h"
#include "bsdiff/patch_writer_interface.h"
namespace bsdiff {
@@ -35,8 +38,12 @@ class EndsleyPatchWriter : public PatchWriterInterface {
public:
// Create the patch writer that will write the data to the passed vector
// |patch|, resizing it as needed. The |patch| vector must be valid until
- // Close() is called or this patch is destroyed.
- explicit EndsleyPatchWriter(std::vector<uint8_t>* patch) : patch_(patch) {}
+ // Close() is called or this patch is destroyed. The data in |patch| will be
+ // compressed using the compressor type |type|.
+ EndsleyPatchWriter(std::vector<uint8_t>* patch,
+ CompressorType type,
+ int quality)
+ : patch_(patch), compressor_type_(type), quality_(quality) {}
// PatchWriterInterface overrides.
bool Init(size_t new_size) override;
@@ -58,6 +65,12 @@ class EndsleyPatchWriter : public PatchWriterInterface {
// The vector we are writing to, owned by the caller.
std::vector<uint8_t>* patch_;
+ // The compressor type to use and its quality (if any).
+ CompressorType compressor_type_;
+ int quality_;
+
+ std::unique_ptr<CompressorInterface> compressor_;
+
// The pending diff and extra data to be encoded in the file. These vectors
// would not be used whenever is possible to the data directly to the patch_
// vector; namely when the control, diff and extra stream data are provided in
diff --git a/endsley_patch_writer_unittest.cc b/endsley_patch_writer_unittest.cc
index 29f404c..456209d 100644
--- a/endsley_patch_writer_unittest.cc
+++ b/endsley_patch_writer_unittest.cc
@@ -31,7 +31,7 @@ class EndsleyPatchWriterTest : public testing::Test {
}
std::vector<uint8_t> data_;
- EndsleyPatchWriter patch_writer_{&data_};
+ EndsleyPatchWriter patch_writer_{&data_, CompressorType::kNoCompression, 0};
};
// Smoke check that a patch includes the new_size and magic header.
@@ -51,6 +51,34 @@ TEST_F(EndsleyPatchWriterTest, CreateEmptyPatchTest) {
EXPECT_EQ(empty_patch, data_);
}
+TEST_F(EndsleyPatchWriterTest, CreateCompressedPatchTest) {
+ EndsleyPatchWriter compressed_writer(&data_, CompressorType::kBZ2, 9);
+
+ auto text = VectorFromString("HelloWorld");
+ EXPECT_TRUE(compressed_writer.Init(text.size()));
+
+ EXPECT_TRUE(compressed_writer.AddControlEntry(ControlEntry(5, 5, -2)));
+ EXPECT_TRUE(compressed_writer.WriteDiffStream(text.data(), 5));
+ EXPECT_TRUE(compressed_writer.WriteExtraStream(text.data() + 5, 5));
+
+ // Check that the output patch had no data written to it before Close() is
+ // called, since we are still compressing it.
+ EXPECT_TRUE(data_.empty());
+
+ EXPECT_TRUE(compressed_writer.Close());
+
+ // Check that the whole file is compressed with BZ2 by looking at the header.
+ const auto bz2_header = VectorFromString("BZh9");
+ data_.resize(4);
+ EXPECT_EQ(bz2_header, data_);
+}
+
+TEST_F(EndsleyPatchWriterTest, CreateEmptyBrotliPatchTest) {
+ EndsleyPatchWriter compressed_writer(&data_, CompressorType::kBrotli, 9);
+ EXPECT_TRUE(compressed_writer.Init(0));
+ EXPECT_TRUE(compressed_writer.Close());
+}
+
// Test we generate the right patch when the control, diff and extra stream come
// in the right order.
TEST_F(EndsleyPatchWriterTest, DataInNiceOrderTest) {
diff --git a/include/bsdiff/patch_writer_factory.h b/include/bsdiff/patch_writer_factory.h
index 7c3613c..64ec4fa 100644
--- a/include/bsdiff/patch_writer_factory.h
+++ b/include/bsdiff/patch_writer_factory.h
@@ -29,13 +29,23 @@ std::unique_ptr<PatchWriterInterface> CreateBSDF2PatchWriter(
CompressorType type,
int quality);
-// Create a patch writer compatible with Android Play Store bsdiff patches,
-// uncompressed. The data will be written to the passed |patch| vector, which
-// must be valid until Close() is called or this patch is destroyed.
+// Create a patch writer compatible with Android Play Store bsdiff patches.
+// The data will be written to the passed |patch| vector, which must be valid
+// until Close() is called or this patch is destroyed. The data will be
+// compressed using the compressor type |type|. To get an uncompressed patch,
+// pass CompressortType::kNoCompression.
+BSDIFF_EXPORT
+std::unique_ptr<PatchWriterInterface> CreateEndsleyPatchWriter(
+ std::vector<uint8_t>* patch,
+ CompressorType type,
+ int quality);
+
+// Helper function to create an Endsley patch writer with no compression.
BSDIFF_EXPORT
std::unique_ptr<PatchWriterInterface> CreateEndsleyPatchWriter(
std::vector<uint8_t>* patch);
+
} // namespace bsdiff
#endif // _BSDIFF_PATCH_WRITER_FACTORY_H_
diff --git a/include/bsdiff/patch_writer_interface.h b/include/bsdiff/patch_writer_interface.h
index 31fc3d8..bc59b36 100644
--- a/include/bsdiff/patch_writer_interface.h
+++ b/include/bsdiff/patch_writer_interface.h
@@ -15,6 +15,7 @@ namespace bsdiff {
enum class BsdiffFormat {
kLegacy,
kBsdf2,
+ kEndsley,
};
class PatchWriterInterface {
diff --git a/patch_writer_factory.cc b/patch_writer_factory.cc
index 95bfe32..8c29bf2 100644
--- a/patch_writer_factory.cc
+++ b/patch_writer_factory.cc
@@ -24,8 +24,17 @@ std::unique_ptr<PatchWriterInterface> CreateBSDF2PatchWriter(
}
std::unique_ptr<PatchWriterInterface> CreateEndsleyPatchWriter(
+ std::vector<uint8_t>* patch,
+ CompressorType type,
+ int quality) {
+ return std::unique_ptr<PatchWriterInterface>(
+ new EndsleyPatchWriter(patch, type, quality));
+}
+
+std::unique_ptr<PatchWriterInterface> CreateEndsleyPatchWriter(
std::vector<uint8_t>* patch) {
- return std::unique_ptr<PatchWriterInterface>(new EndsleyPatchWriter(patch));
+ return std::unique_ptr<PatchWriterInterface>(
+ new EndsleyPatchWriter(patch, CompressorType::kNoCompression, 0));
}
} // namespace bsdiff
diff --git a/utils.cc b/utils.cc
index bcaba65..c3e613e 100644
--- a/utils.cc
+++ b/utils.cc
@@ -1,3 +1,7 @@
+// Copyright 2018 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
#include "bsdiff/utils.h"
namespace bsdiff {