Add functions in recovery/minzip to libziparchive
Add two functions libziparchive that libminzip has. And create
corresponding unit tests.
1. Open a zip archive from a memory mapped region.
2. A new writer that takes a call back function pointer.
(Used by the OTA updater to stream the data.)
Test: Unit tests passed
Bug: 19472796
Change-Id: I2b2daec71174afe221030357e39bff5faea51e72
diff --git a/zip_archive_private.h b/zip_archive_private.h
index ab52368..971db4f 100644
--- a/zip_archive_private.h
+++ b/zip_archive_private.h
@@ -21,17 +21,83 @@
#include <stdlib.h>
#include <unistd.h>
+#include <memory>
+#include <vector>
+
#include <utils/FileMap.h>
#include <ziparchive/zip_archive.h>
+class MappedZipFile {
+ public:
+ explicit MappedZipFile(const int fd) :
+ has_fd_(true),
+ fd_(fd),
+ base_ptr_(nullptr),
+ data_length_(0),
+ read_pos_(0) {}
+
+ explicit MappedZipFile(void* address, size_t length) :
+ has_fd_(false),
+ fd_(-1),
+ base_ptr_(address),
+ data_length_(static_cast<off64_t>(length)),
+ read_pos_(0) {}
+
+ bool HasFd() const {return has_fd_;}
+
+ int GetFileDescriptor() const;
+
+ void* GetBasePtr() const;
+
+ off64_t GetFileLength() const;
+
+ bool SeekToOffset(off64_t offset);
+
+ bool ReadData(uint8_t* buffer, size_t read_amount);
+
+ bool ReadAtOffset(uint8_t* buf, size_t len, off64_t off);
+
+ private:
+ // If has_fd_ is true, fd is valid and we'll read contents of a zip archive
+ // from the file. Otherwise, we're opening the archive from a memory mapped
+ // file. In that case, base_ptr_ points to the start of the memory region and
+ // data_length_ defines the file length.
+ const bool has_fd_;
+
+ const int fd_;
+
+ void* const base_ptr_;
+ const off64_t data_length_;
+ // read_pos_ is the offset to the base_ptr_ where we read data from.
+ size_t read_pos_;
+};
+
+class CentralDirectory {
+ public:
+ CentralDirectory(void) :
+ base_ptr_(nullptr),
+ length_(0) {}
+
+ const uint8_t* GetBasePtr() const {return base_ptr_;}
+
+ size_t GetMapLength() const {return length_;}
+
+ void Initialize(void* map_base_ptr, off64_t cd_start_offset, size_t cd_size);
+
+ private:
+ const uint8_t* base_ptr_;
+ size_t length_;
+};
+
struct ZipArchive {
// open Zip archive
- const int fd;
+ mutable MappedZipFile mapped_zip;
const bool close_file;
// mapped central directory area
off64_t directory_offset;
- android::FileMap directory_map;
+ CentralDirectory central_directory;
+ std::unique_ptr<android::FileMap> directory_map;
// number of entries in the Zip archive
uint16_t num_entries;
@@ -44,20 +110,36 @@
ZipString* hash_table;
ZipArchive(const int fd, bool assume_ownership) :
- fd(fd),
- close_file(assume_ownership),
- directory_offset(0),
- num_entries(0),
- hash_table_size(0),
- hash_table(NULL) {}
+ mapped_zip(fd),
+ close_file(assume_ownership),
+ directory_offset(0),
+ central_directory(),
+ directory_map(new android::FileMap()),
+ num_entries(0),
+ hash_table_size(0),
+ hash_table(nullptr) {}
+
+ ZipArchive(void* address, size_t length) :
+ mapped_zip(address, length),
+ close_file(false),
+ directory_offset(0),
+ central_directory(),
+ directory_map(new android::FileMap()),
+ num_entries(0),
+ hash_table_size(0),
+ hash_table(nullptr) {}
~ZipArchive() {
- if (close_file && fd >= 0) {
- close(fd);
+ if (close_file && mapped_zip.GetFileDescriptor() >= 0) {
+ close(mapped_zip.GetFileDescriptor());
}
free(hash_table);
}
+
+ bool InitializeCentralDirectory(const char* debug_file_name, off64_t cd_start_offset,
+ size_t cd_size);
+
};
#endif // LIBZIPARCHIVE_ZIPARCHIVE_PRIVATE_H_