zip_archive_private.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. * Copyright (C) 2008 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #pragma once
  17. #include <ziparchive/zip_archive.h>
  18. #include <stdint.h>
  19. #include <stdlib.h>
  20. #include <unistd.h>
  21. #include <memory>
  22. #include <vector>
  23. #include "android-base/macros.h"
  24. #include "android-base/mapped_file.h"
  25. static const char* kErrorMessages[] = {
  26. "Success",
  27. "Iteration ended",
  28. "Zlib error",
  29. "Invalid file",
  30. "Invalid handle",
  31. "Duplicate entries in archive",
  32. "Empty archive",
  33. "Entry not found",
  34. "Invalid offset",
  35. "Inconsistent information",
  36. "Invalid entry name",
  37. "I/O error",
  38. "File mapping failed",
  39. };
  40. enum ErrorCodes : int32_t {
  41. kIterationEnd = -1,
  42. // We encountered a Zlib error when inflating a stream from this file.
  43. // Usually indicates file corruption.
  44. kZlibError = -2,
  45. // The input file cannot be processed as a zip archive. Usually because
  46. // it's too small, too large or does not have a valid signature.
  47. kInvalidFile = -3,
  48. // An invalid iteration / ziparchive handle was passed in as an input
  49. // argument.
  50. kInvalidHandle = -4,
  51. // The zip archive contained two (or possibly more) entries with the same
  52. // name.
  53. kDuplicateEntry = -5,
  54. // The zip archive contains no entries.
  55. kEmptyArchive = -6,
  56. // The specified entry was not found in the archive.
  57. kEntryNotFound = -7,
  58. // The zip archive contained an invalid local file header pointer.
  59. kInvalidOffset = -8,
  60. // The zip archive contained inconsistent entry information. This could
  61. // be because the central directory & local file header did not agree, or
  62. // if the actual uncompressed length or crc32 do not match their declared
  63. // values.
  64. kInconsistentInformation = -9,
  65. // An invalid entry name was encountered.
  66. kInvalidEntryName = -10,
  67. // An I/O related system call (read, lseek, ftruncate, map) failed.
  68. kIoError = -11,
  69. // We were not able to mmap the central directory or entry contents.
  70. kMmapFailed = -12,
  71. kLastErrorCode = kMmapFailed,
  72. };
  73. class MappedZipFile {
  74. public:
  75. explicit MappedZipFile(const int fd)
  76. : has_fd_(true), fd_(fd), base_ptr_(nullptr), data_length_(0) {}
  77. explicit MappedZipFile(void* address, size_t length)
  78. : has_fd_(false), fd_(-1), base_ptr_(address), data_length_(static_cast<off64_t>(length)) {}
  79. bool HasFd() const { return has_fd_; }
  80. int GetFileDescriptor() const;
  81. void* GetBasePtr() const;
  82. off64_t GetFileLength() const;
  83. bool ReadAtOffset(uint8_t* buf, size_t len, off64_t off) const;
  84. private:
  85. // If has_fd_ is true, fd is valid and we'll read contents of a zip archive
  86. // from the file. Otherwise, we're opening the archive from a memory mapped
  87. // file. In that case, base_ptr_ points to the start of the memory region and
  88. // data_length_ defines the file length.
  89. const bool has_fd_;
  90. const int fd_;
  91. void* const base_ptr_;
  92. const off64_t data_length_;
  93. };
  94. class CentralDirectory {
  95. public:
  96. CentralDirectory(void) : base_ptr_(nullptr), length_(0) {}
  97. const uint8_t* GetBasePtr() const { return base_ptr_; }
  98. size_t GetMapLength() const { return length_; }
  99. void Initialize(void* map_base_ptr, off64_t cd_start_offset, size_t cd_size);
  100. private:
  101. const uint8_t* base_ptr_;
  102. size_t length_;
  103. };
  104. /**
  105. * More space efficient string representation of strings in an mmaped zipped file than
  106. * std::string_view or ZipString. Using ZipString as an entry in the ZipArchive hashtable wastes
  107. * space. ZipString stores a pointer to a string (on 64 bit, 8 bytes) and the length to read from
  108. * that pointer, 2 bytes. Because of alignment, the structure consumes 16 bytes, wasting 6 bytes.
  109. * ZipStringOffset stores a 4 byte offset from a fixed location in the memory mapped file instead
  110. * of the entire address, consuming 8 bytes with alignment.
  111. */
  112. struct ZipStringOffset {
  113. uint32_t name_offset;
  114. uint16_t name_length;
  115. const ZipString GetZipString(const uint8_t* start) const {
  116. ZipString zip_string;
  117. zip_string.name = start + name_offset;
  118. zip_string.name_length = name_length;
  119. return zip_string;
  120. }
  121. };
  122. struct ZipArchive {
  123. // open Zip archive
  124. mutable MappedZipFile mapped_zip;
  125. const bool close_file;
  126. // mapped central directory area
  127. off64_t directory_offset;
  128. CentralDirectory central_directory;
  129. std::unique_ptr<android::base::MappedFile> directory_map;
  130. // number of entries in the Zip archive
  131. uint16_t num_entries;
  132. // We know how many entries are in the Zip archive, so we can have a
  133. // fixed-size hash table. We define a load factor of 0.75 and over
  134. // allocate so the maximum number entries can never be higher than
  135. // ((4 * UINT16_MAX) / 3 + 1) which can safely fit into a uint32_t.
  136. uint32_t hash_table_size;
  137. ZipStringOffset* hash_table;
  138. ZipArchive(const int fd, bool assume_ownership);
  139. ZipArchive(void* address, size_t length);
  140. ~ZipArchive();
  141. bool InitializeCentralDirectory(off64_t cd_start_offset, size_t cd_size);
  142. };