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

Commit 4928d8d0 authored by Narayan Kamath's avatar Narayan Kamath Committed by Gerrit Code Review
Browse files

Merge "Fix ExtractEntryToFile."

parents d5f97db5 00a258ce
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -152,7 +152,10 @@ int32_t StartIteration(ZipArchiveHandle handle, void** cookie_ptr,
int32_t Next(void* cookie, ZipEntry* data, ZipEntryName *name);

/*
 * Uncompress and write an entry to a file descriptor.
 * Uncompress and write an entry to an open file identified by |fd|.
 * |entry->uncompressed_length| bytes will be written to the file at
 * its current offset, and the file will be truncated at the end of
 * the uncompressed data.
 *
 * Returns 0 on success and negative values on failure.
 */
+11 −3
Original line number Diff line number Diff line
@@ -1007,13 +1007,21 @@ int32_t ExtractEntryToFile(ZipArchiveHandle handle,
                           ZipEntry* entry, int fd) {
  const int32_t declared_length = entry->uncompressed_length;

  int result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length));
  const off64_t current_offset = lseek64(fd, 0, SEEK_CUR);
  if (current_offset == -1) {
    ALOGW("Zip: unable to seek to current location on fd %d: %s", fd,
          strerror(errno));
    return kIoError;
  }

  int result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length + current_offset));
  if (result == -1) {
    ALOGW("Zip: unable to truncate file to %ud", declared_length);
    ALOGW("Zip: unable to truncate file to %lld: %s", declared_length + current_offset,
          strerror(errno));
    return kIoError;
  }

  android::FileMap* map  = MapFileSegment(fd, 0, declared_length,
  android::FileMap* map  = MapFileSegment(fd, current_offset, declared_length,
                                          false, kTempMappingFileName);
  if (map == NULL) {
    return kMmapFailed;
+42 −1
Original line number Diff line number Diff line
@@ -16,8 +16,12 @@

#include "ziparchive/zip_archive.h"

#include "getopt.h"
#include <errno.h>
#include <getopt.h>
#include <stdio.h>
#include <unistd.h>
#include <vector>

#include <gtest/gtest.h>

static std::string test_data_dir;
@@ -136,6 +140,43 @@ TEST(ziparchive, ExtractToMemory) {
  CloseArchive(handle);
}

TEST(ziparchive, ExtractToFile) {
  char kTempFilePattern[] = "zip_archive_test_XXXXXX";
  int fd = mkstemp(kTempFilePattern);
  ASSERT_NE(-1, fd);
  const uint8_t data[8] = { '1', '2', '3', '4', '5', '6', '7', '8' };
  const ssize_t data_size = sizeof(data);

  ASSERT_EQ(data_size, TEMP_FAILURE_RETRY(write(fd, data, data_size)));

  ZipArchiveHandle handle;
  ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));

  ZipEntry entry;
  ASSERT_EQ(0, FindEntry(handle, "a.txt", &entry));
  ASSERT_EQ(0, ExtractEntryToFile(handle, &entry, fd));


  // Assert that the first 8 bytes of the file haven't been clobbered.
  uint8_t read_buffer[data_size];
  ASSERT_EQ(0, lseek64(fd, 0, SEEK_SET));
  ASSERT_EQ(data_size, TEMP_FAILURE_RETRY(read(fd, read_buffer, data_size)));
  ASSERT_EQ(0, memcmp(read_buffer, data, data_size));

  // Assert that the remainder of the file contains the incompressed data.
  std::vector<uint8_t> uncompressed_data(entry.uncompressed_length);
  ASSERT_EQ(static_cast<ssize_t>(entry.uncompressed_length),
            TEMP_FAILURE_RETRY(
                read(fd, &uncompressed_data[0], entry.uncompressed_length)));
  ASSERT_EQ(0, memcmp(&uncompressed_data[0], kATxtContents,
                      sizeof(kATxtContents)));

  // Assert that the total length of the file is sane
  ASSERT_EQ(data_size + sizeof(kATxtContents), lseek64(fd, 0, SEEK_END));

  close(fd);
}

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);