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_