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

Commit 69055b5a authored by Donald Chai's avatar Donald Chai Committed by Gerrit Code Review
Browse files

Merge "Avoid using data descriptors in ZIP files when possible."

parents b42e558b e170d7fe
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -76,6 +76,10 @@ cc_defaults {
        "liblog",
    ],

    // for FRIEND_TEST
    static_libs: ["libgtest_prod"],
    export_static_lib_headers: ["libgtest_prod"],

    export_include_dirs: ["include"],
}

+4 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <cstdio>
#include <ctime>

#include <gtest/gtest_prod.h>
#include <memory>
#include <string>
#include <string_view>
@@ -165,6 +166,7 @@ class ZipWriter {
  int32_t StoreBytes(FileEntry* file, const void* data, uint32_t len);
  int32_t CompressBytes(FileEntry* file, const void* data, uint32_t len);
  int32_t FlushCompressedBytes(FileEntry* file);
  bool ShouldUseDataDescriptor() const;

  enum class State {
    kWritingZip,
@@ -182,4 +184,6 @@ class ZipWriter {

  std::unique_ptr<z_stream, void (*)(z_stream*)> z_stream_;
  std::vector<uint8_t> buffer_;

  FRIEND_TEST(zipwriter, WriteToUnseekableFile);
};
+7 −2
Original line number Diff line number Diff line
@@ -455,6 +455,11 @@ int32_t ZipWriter::FlushCompressedBytes(FileEntry* file) {
  return kNoError;
}

bool ZipWriter::ShouldUseDataDescriptor() const {
  // Only use a trailing "data descriptor" if the output isn't seekable.
  return !seekable_;
}

int32_t ZipWriter::FinishEntry() {
  if (state_ != State::kWritingEntry) {
    return kInvalidState;
@@ -467,7 +472,7 @@ int32_t ZipWriter::FinishEntry() {
    }
  }

  if ((current_file_entry_.compression_method & kCompressDeflated) || !seekable_) {
  if (ShouldUseDataDescriptor()) {
    // Some versions of ZIP don't allow STORED data to have a trailing DataDescriptor.
    // If this file is not seekable, or if the data is compressed, write a DataDescriptor.
    const uint32_t sig = DataDescriptor::kOptSignature;
@@ -515,7 +520,7 @@ int32_t ZipWriter::Finish() {
  for (FileEntry& file : files_) {
    CentralDirectoryRecord cdr = {};
    cdr.record_signature = CentralDirectoryRecord::kSignature;
    if ((file.compression_method & kCompressDeflated) || !seekable_) {
    if (ShouldUseDataDescriptor()) {
      cdr.gpb_flags |= kGPBDDFlagMask;
    }
    cdr.compression_method = file.compression_method;
+24 −0
Original line number Diff line number Diff line
@@ -243,6 +243,7 @@ TEST_F(zipwriter, WriteCompressedZipWithOneFile) {
  ZipEntry data;
  ASSERT_EQ(0, FindEntry(handle, "file.txt", &data));
  EXPECT_EQ(kCompressDeflated, data.method);
  EXPECT_EQ(0u, data.has_data_descriptor);
  ASSERT_EQ(4u, data.uncompressed_length);
  ASSERT_TRUE(AssertFileEntryContentsEq("helo", handle, &data));

@@ -351,6 +352,29 @@ TEST_F(zipwriter, BackupRemovesTheLastFile) {
  CloseArchive(handle);
}

TEST_F(zipwriter, WriteToUnseekableFile) {
  const char* expected = "hello";
  ZipWriter writer(file_);
  writer.seekable_ = false;

  ASSERT_EQ(0, writer.StartEntry("file.txt", 0));
  ASSERT_EQ(0, writer.WriteBytes(expected, strlen(expected)));
  ASSERT_EQ(0, writer.FinishEntry());
  ASSERT_EQ(0, writer.Finish());
  ASSERT_GE(0, lseek(fd_, 0, SEEK_SET));

  ZipArchiveHandle handle;
  ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
  ZipEntry data;
  ASSERT_EQ(0, FindEntry(handle, "file.txt", &data));
  EXPECT_EQ(kCompressStored, data.method);
  EXPECT_EQ(1u, data.has_data_descriptor);
  EXPECT_EQ(strlen(expected), data.compressed_length);
  ASSERT_EQ(strlen(expected), data.uncompressed_length);
  ASSERT_TRUE(AssertFileEntryContentsEq(expected, handle, &data));
  CloseArchive(handle);
}

TEST_F(zipwriter, TruncateFileAfterBackup) {
  ZipWriter writer(file_);