| OLD | NEW |
| 1 // Copyright 2014 The Chromium OS Authors. All rights reserved. | 1 // Copyright 2014 The Chromium OS Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef VOLUME_ARCHIVE_LIBARCHIVE_H_ | 5 #ifndef VOLUME_ARCHIVE_LIBARCHIVE_H_ |
| 6 #define VOLUME_ARCHIVE_LIBARCHIVE_H_ | 6 #define VOLUME_ARCHIVE_LIBARCHIVE_H_ |
| 7 | 7 |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "archive.h" | 10 #include "third_party/zlib/contrib/minizip/unzip.h" |
| 11 #include "third_party/zlib/contrib/minizip/zip.h" |
| 11 | 12 |
| 12 #include "volume_archive.h" | 13 #include "volume_archive.h" |
| 13 | 14 |
| 14 // A namespace with constants used by VolumeArchiveLibarchive. | 15 // A namespace with constants used by VolumeArchiveLibarchive. |
| 15 namespace volume_archive_constants { | 16 namespace volume_archive_constants { |
| 16 | 17 |
| 17 const char kArchiveReadNewError[] = "Could not allocate archive."; | 18 const char kArchiveReadNewError[] = "Could not allocate archive."; |
| 18 const char kFileNotFound[] = "File not found for read data request."; | 19 const char kFileNotFound[] = "File not found for read data request."; |
| 19 const char kVolumeReaderError[] = "VolumeReader failed to retrieve data."; | 20 const char kVolumeReaderError[] = "VolumeReader failed to retrieve data."; |
| 20 const char kArchiveSupportErrorPrefix[] = "Error at support rar/zip format: "; | 21 const char kArchiveOpenError[] = "Failed to open archive."; |
| 21 const char kArchiveOpenErrorPrefix[] = "Error at open archive: "; | 22 const char kArchiveNextHeaderError[] = |
| 22 const char kArchiveNextHeaderErrorPrefix[] = | 23 "Failed to open current file in archive."; |
| 23 "Error at reading next header for metadata: "; | 24 const char kArchiveReadDataError[] = "Failed to read archive data."; |
| 24 const char kArchiveReadDataErrorPrefix[] = "Error at reading data: "; | 25 const char kArchiveReadFreeError[] = "Failed to close archive."; |
| 25 const char kArchiveReadFreeErrorPrefix[] = "Error at archive free: "; | |
| 26 | 26 |
| 27 // The size of the buffer used to skip unnecessary data. | 27 // The size of the buffer used to skip unnecessary data. |
| 28 // Should be positive and less than size_t maximum. | 28 // Should be positive and less than size_t maximum. |
| 29 const int64_t kDummyBufferSize = 512 * 1024; // 512 KB | 29 const int64_t kDummyBufferSize = 512 * 1024; // 512 KB |
| 30 | 30 |
| 31 // The size of the buffer used by ReadInProgress to decompress data. | 31 // The size of the buffer used by ReadInProgress to decompress data. |
| 32 // Should be positive and less than size_t maximum. | 32 // Should be positive and less than size_t maximum. |
| 33 const int64_t kDecompressBufferSize = 512 * 1024; // 512 KB. | 33 const int64_t kDecompressBufferSize = 512 * 1024; // 512 KB. |
| 34 | 34 |
| 35 // The maximum data chunk size for VolumeReader::Read requests. | 35 // The maximum data chunk size for VolumeReader::Read requests. |
| 36 // Should be positive. | 36 // Should be positive. |
| 37 const int64_t kMaximumDataChunkSize = 512 * 1024; // 512 KB. | 37 const int64_t kMaximumDataChunkSize = 512 * 1024; // 512 KB. |
| 38 | 38 |
| 39 // The minimum data chunk size for VolumeReader::Read requests. | 39 // The minimum data chunk size for VolumeReader::Read requests. |
| 40 // Should be positive. | 40 // Should be positive. |
| 41 const int64_t kMinimumDataChunkSize = 32 * 1024; // 16 KB. | 41 const int64_t kMinimumDataChunkSize = 32 * 1024; // 16 KB. |
| 42 | 42 |
| 43 // Maximum length of filename in zip archive. |
| 44 const int kZipMaxPath = 256; |
| 45 |
| 46 // The size of the static cache. We need at least 64KB to cache whole |
| 47 // 'end of central directory' data. |
| 48 const int64_t kStaticCacheSize = 128 * 1024; |
| 49 |
| 43 } // namespace volume_archive_constants | 50 } // namespace volume_archive_constants |
| 44 | 51 |
| 52 class VolumeArchiveLibarchive; |
| 53 |
| 54 // A namespace with custom functions passed to minizip. |
| 55 namespace volume_archive_functions { |
| 56 |
| 57 int64_t DynamicCache(VolumeArchiveLibarchive* archive, int64_t unz_size); |
| 58 |
| 59 uLong CustomArchiveRead(void* archive, void* stream, void* buf, uLong size); |
| 60 |
| 61 // Returns the offset from the beginning of the data. |
| 62 long CustomArchiveTell(void* archive, void* stream); |
| 63 |
| 64 // Moves the current offset to the specified position. |
| 65 long CustomArchiveSeek(void* archive, |
| 66 void* stream, |
| 67 uLong offset, |
| 68 int origin); |
| 69 |
| 70 } // compressor_archive_functions |
| 71 |
| 72 |
| 73 class VolumeArchiveLibarchive; |
| 74 |
| 45 // Defines an implementation of VolumeArchive that wraps all libarchive | 75 // Defines an implementation of VolumeArchive that wraps all libarchive |
| 46 // operations. | 76 // operations. |
| 47 class VolumeArchiveLibarchive : public VolumeArchive { | 77 class VolumeArchiveLibarchive : public VolumeArchive { |
| 48 public: | 78 public: |
| 49 explicit VolumeArchiveLibarchive(VolumeReader* reader); | 79 explicit VolumeArchiveLibarchive(VolumeReader* reader); |
| 50 | 80 |
| 51 virtual ~VolumeArchiveLibarchive(); | 81 virtual ~VolumeArchiveLibarchive(); |
| 52 | 82 |
| 53 // See volume_archive_interface.h. | 83 // See volume_archive_interface.h. |
| 54 virtual bool Init(const std::string& encoding); | 84 virtual bool Init(const std::string& encoding); |
| 55 | 85 |
| 56 // See volume_archive_interface.h. | 86 // See volume_archive_interface.h. |
| 57 virtual Result GetNextHeader(); | 87 virtual VolumeArchive::Result GetCurrentFileInfo(std::string* path_name, |
| 58 virtual Result GetNextHeader(const char** path_name, | 88 int64_t* size, |
| 59 int64_t* size, | 89 bool* is_directory, |
| 60 bool* is_directory, | 90 time_t* modification_time); |
| 61 time_t* modification_time); | 91 |
| 92 virtual VolumeArchive::Result GoToNextFile(); |
| 62 | 93 |
| 63 // See volume_archive_interface.h. | 94 // See volume_archive_interface.h. |
| 64 virtual bool SeekHeader(int64_t index); | 95 virtual bool SeekHeader(const std::string& path_name); |
| 65 | 96 |
| 66 // See volume_archive_interface.h. | 97 // See volume_archive_interface.h. |
| 67 virtual int64_t ReadData(int64_t offset, | 98 virtual int64_t ReadData(int64_t offset, int64_t length, const char** buffer); |
| 68 int64_t length, | |
| 69 const char** buffer); | |
| 70 | 99 |
| 71 // See volume_archive_interface.h. | 100 // See volume_archive_interface.h. |
| 72 virtual void MaybeDecompressAhead(); | 101 virtual void MaybeDecompressAhead(); |
| 73 | 102 |
| 74 // See volume_archive_interface.h. | 103 // See volume_archive_interface.h. |
| 75 virtual bool Cleanup(); | 104 virtual bool Cleanup(); |
| 76 | 105 |
| 77 int64_t reader_data_size() const { return reader_data_size_; } | 106 int64_t reader_data_size() const { return reader_data_size_; } |
| 78 | 107 |
| 108 // Custom functions need to access private variables of |
| 109 // CompressorArchiveLibarchive frequently. |
| 110 friend int64_t volume_archive_functions::DynamicCache( |
| 111 VolumeArchiveLibarchive* va, int64_t unz_size); |
| 112 |
| 113 friend uLong volume_archive_functions::CustomArchiveRead( |
| 114 void* archive, void* stream, void* buf, uLong size); |
| 115 |
| 116 friend long volume_archive_functions::CustomArchiveTell( |
| 117 void* archive, void* stream); |
| 118 |
| 119 friend long volume_archive_functions::CustomArchiveSeek( |
| 120 void* archive, void* stream, uLong offset, int origin); |
| 121 |
| 79 private: | 122 private: |
| 80 // Decompress length bytes of data starting from offset. | 123 // Decompress length bytes of data starting from offset. |
| 81 void DecompressData(int64_t offset, int64_t length); | 124 void DecompressData(int64_t offset, int64_t length); |
| 82 | 125 |
| 83 // The size of the requested data from VolumeReader. | 126 // The size of the requested data from VolumeReader. |
| 84 int64_t reader_data_size_; | 127 int64_t reader_data_size_; |
| 85 | 128 |
| 86 // The libarchive correspondent archive object. | 129 // The minizip correspondent archive object. |
| 87 archive* archive_; | 130 zipFile zip_file_; |
| 88 | 131 |
| 89 // The last reached entry with VolumeArchiveLibarchive::GetNextHeader. | 132 // We use two kinds of cache strategies here: dynamic and static. |
| 90 archive_entry* current_archive_entry_; | 133 // Dynamic cache is a common cache strategy used in most of IO streams such as |
| 134 // fread. When a file chunk is requested and if the size of the requested |
| 135 // chunk is small, we load larger size of bytes from the archive and cache |
| 136 // them in dynamic_cache_. If the range of the next requested chunk is within |
| 137 // the cache, we don't read the archive and just return the data in the cache. |
| 138 char dynamic_cache_[volume_archive_constants::kMaximumDataChunkSize]; |
| 139 |
| 140 // The offset from which dynamic_cache_ has the data of the archive. |
| 141 int64_t dynamic_cache_offset_; |
| 142 |
| 143 // The size of the data in dynamic_cache_. |
| 144 int64_t dynamic_cache_size_; |
| 145 |
| 146 // Although dynamic cache works in most situations, it doesn't work when |
| 147 // MiniZip is looking for the front index of the central directory. Since |
| 148 // MiniZip reads the data little by little backwards from the end to find the |
| 149 // index, dynamic_cache will be reloaded every time. To avoid this, we first |
| 150 // cache a certain length of data from the end into static_cache_. The data |
| 151 // in this buffer is also used when the data in the central directory is |
| 152 // requested by MiniZip later. |
| 153 char static_cache_[volume_archive_constants::kStaticCacheSize]; |
| 154 |
| 155 // The offset from which static_cache_ has the data of the archive. |
| 156 int64_t static_cache_offset_; |
| 157 |
| 158 // The size of the data in static_cache_. The End Of Central Directory header |
| 159 // is guaranteed to be in the last 64(global comment) + 1(other fields) of the |
| 160 // file. This cache is used to store the header. |
| 161 int64_t static_cache_size_; |
| 91 | 162 |
| 92 // The data offset, which will be offset + length after last read | 163 // The data offset, which will be offset + length after last read |
| 93 // operation, where offset and length are method parameters for | 164 // operation, where offset and length are method parameters for |
| 94 // VolumeArchiveLibarchive::ReadData. Data offset is used to improve | 165 // VolumeArchiveLibarchive::ReadData. Data offset is used to improve |
| 95 // performance for consecutive calls to VolumeArchiveLibarchive::ReadData. | 166 // performance for consecutive calls to VolumeArchiveLibarchive::ReadData. |
| 96 // | 167 // |
| 97 // Intead of starting the read from the beginning for every | 168 // Intead of starting the read from the beginning for every |
| 98 // VolumeArchiveLibarchive::ReadData, the next call will start | 169 // VolumeArchiveLibarchive::ReadData, the next call will start |
| 99 // from last_read_data_offset_ in case the offset parameter of | 170 // from last_read_data_offset_ in case the offset parameter of |
| 100 // VolumeArchiveLibarchive::ReadData has the same value as | 171 // VolumeArchiveLibarchive::ReadData has the same value as |
| (...skipping 27 matching lines...) Expand all Loading... |
| 128 | 199 |
| 129 // The size of valid data starting from decompressed_data_ that is stored | 200 // The size of valid data starting from decompressed_data_ that is stored |
| 130 // inside decompressed_data_buffer_. | 201 // inside decompressed_data_buffer_. |
| 131 int64_t decompressed_data_size_; | 202 int64_t decompressed_data_size_; |
| 132 | 203 |
| 133 // True if VolumeArchiveLibarchive::DecompressData failed. | 204 // True if VolumeArchiveLibarchive::DecompressData failed. |
| 134 bool decompressed_error_; | 205 bool decompressed_error_; |
| 135 }; | 206 }; |
| 136 | 207 |
| 137 #endif // VOLUME_ARCHIVE_LIBARCHIVE_H_ | 208 #endif // VOLUME_ARCHIVE_LIBARCHIVE_H_ |
| OLD | NEW |