Chromium Code Reviews| 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; | |
| 43 } // namespace volume_archive_constants | 49 } // namespace volume_archive_constants |
|
mtomasz
2017/04/10 07:15:09
nit: \n missing before } for consistency with \n a
takise
2017/04/11 06:00:52
Done.
| |
| 44 | 50 |
| 51 class VolumeArchiveLibarchive; | |
| 52 | |
| 53 // A name space with custom functions passed to minizip. | |
|
mtomasz
2017/04/10 07:15:09
nit: name space -> namespace
takise
2017/04/11 06:00:52
Done.
| |
| 54 namespace volume_archive_functions { | |
| 55 int64_t DynamicCache(VolumeArchiveLibarchive* va, int64_t unz_size); | |
| 56 uLong CustomArchiveRead(void* opaque, void* /*stream*/, void* buf, uLong size) ; | |
| 57 // Returns the offset from the beginning of the data. | |
| 58 long CustomArchiveTell(void* opaque, void* /*stream*/); | |
|
mtomasz
2017/04/10 07:15:09
nit: Can we have an empty line between functions?
takise
2017/04/11 06:00:52
Done.
| |
| 59 // Moves the current offset to the specified position. | |
| 60 long CustomArchiveSeek(void* opaque, | |
| 61 void* /*stream*/, | |
| 62 uLong offset, | |
| 63 int origin); | |
| 64 } // compressor_archive_functions | |
|
mtomasz
2017/04/10 07:15:09
nit: \s\s before //
takise
2017/04/11 06:00:52
Done.
| |
| 65 | |
| 66 | |
| 67 class VolumeArchiveLibarchive; | |
| 68 | |
| 45 // Defines an implementation of VolumeArchive that wraps all libarchive | 69 // Defines an implementation of VolumeArchive that wraps all libarchive |
| 46 // operations. | 70 // operations. |
| 47 class VolumeArchiveLibarchive : public VolumeArchive { | 71 class VolumeArchiveLibarchive : public VolumeArchive { |
| 48 public: | 72 public: |
| 49 explicit VolumeArchiveLibarchive(VolumeReader* reader); | 73 explicit VolumeArchiveLibarchive(VolumeReader* reader); |
| 50 | 74 |
| 51 virtual ~VolumeArchiveLibarchive(); | 75 virtual ~VolumeArchiveLibarchive(); |
| 52 | 76 |
| 53 // See volume_archive_interface.h. | 77 // See volume_archive_interface.h. |
| 54 virtual bool Init(const std::string& encoding); | 78 virtual bool Init(const std::string& encoding); |
| 55 | 79 |
| 56 // See volume_archive_interface.h. | 80 // See volume_archive_interface.h. |
| 57 virtual Result GetNextHeader(); | 81 virtual VolumeArchive::Result GetCurrentFileInfo(std::string* path_name, |
| 58 virtual Result GetNextHeader(const char** path_name, | 82 int64_t* size, |
| 59 int64_t* size, | 83 bool* is_directory, |
| 60 bool* is_directory, | 84 time_t* modification_time); |
| 61 time_t* modification_time); | 85 |
| 86 virtual VolumeArchive::Result GoToNextFile(); | |
| 62 | 87 |
| 63 // See volume_archive_interface.h. | 88 // See volume_archive_interface.h. |
| 64 virtual bool SeekHeader(int64_t index); | 89 virtual bool SeekHeader(const std::string& path_name); |
| 65 | 90 |
| 66 // See volume_archive_interface.h. | 91 // See volume_archive_interface.h. |
| 67 virtual int64_t ReadData(int64_t offset, | 92 virtual int64_t ReadData(int64_t offset, int64_t length, const char** buffer); |
| 68 int64_t length, | |
| 69 const char** buffer); | |
| 70 | 93 |
| 71 // See volume_archive_interface.h. | 94 // See volume_archive_interface.h. |
| 72 virtual void MaybeDecompressAhead(); | 95 virtual void MaybeDecompressAhead(); |
| 73 | 96 |
| 74 // See volume_archive_interface.h. | 97 // See volume_archive_interface.h. |
| 75 virtual bool Cleanup(); | 98 virtual bool Cleanup(); |
| 76 | 99 |
| 77 int64_t reader_data_size() const { return reader_data_size_; } | 100 int64_t reader_data_size() const { return reader_data_size_; } |
| 78 | 101 |
| 102 // Custom functions need to access private variables of | |
| 103 // CompressorArchiveLibarchive frequently. | |
| 104 friend int64_t volume_archive_functions::DynamicCache( | |
| 105 VolumeArchiveLibarchive* va, int64_t unz_size); | |
| 106 friend uLong volume_archive_functions::CustomArchiveRead( | |
| 107 void* opaque, void* /*stream*/, void* buf, uLong size); | |
|
mtomasz
2017/04/10 07:15:09
nit: No need for commenting out arguments in heade
takise
2017/04/11 06:00:52
Done.
| |
| 108 friend long volume_archive_functions::CustomArchiveTell( | |
| 109 void* opaque, void* /*stream*/); | |
| 110 friend long volume_archive_functions::CustomArchiveSeek( | |
| 111 void* opaque, void* /*stream*/, uLong offset, int origin); | |
| 112 | |
| 79 private: | 113 private: |
| 80 // Decompress length bytes of data starting from offset. | 114 // Decompress length bytes of data starting from offset. |
| 81 void DecompressData(int64_t offset, int64_t length); | 115 void DecompressData(int64_t offset, int64_t length); |
| 82 | 116 |
| 83 // The size of the requested data from VolumeReader. | 117 // The size of the requested data from VolumeReader. |
| 84 int64_t reader_data_size_; | 118 int64_t reader_data_size_; |
| 85 | 119 |
| 86 // The libarchive correspondent archive object. | 120 // The minizip correspondent archive object. |
| 87 archive* archive_; | 121 zipFile zip_file_; |
| 88 | 122 |
| 89 // The last reached entry with VolumeArchiveLibarchive::GetNextHeader. | 123 // We use two kinds of cache strategies here: dynamic and static. |
| 90 archive_entry* current_archive_entry_; | 124 // Dynamic cache is a common cache strategy used in most of IO streams such as |
| 125 // fread. When a file chunk is requested and if the size of the requested | |
| 126 // chunk is small, we load larger size of bytes from the archive and cache | |
| 127 // them in dynamic_cache_. If the range of the next requested chunk is within | |
| 128 // the cache, we don't read the archive and just return the data in the cache. | |
| 129 char dynamic_cache_[volume_archive_constants::kMaximumDataChunkSize]; | |
| 130 | |
| 131 // The offset from which dynamic_cache_ has the data of the archive. | |
| 132 int64_t dynamic_cache_offset_; | |
| 133 | |
| 134 // The size of the data in dynamic_cache_. | |
| 135 int64_t dynamic_cache_size_; | |
| 136 | |
| 137 // Although dynamic cache works in most situations, it doesn't work when | |
| 138 // MiniZip is looking for the front index of the central directory. Since | |
| 139 // MiniZip reads the data little by little backwards from the end to find the | |
| 140 // index, dynamic_cache will be reloaded every time. To avoid this, we first | |
| 141 // cache a certain length of data from the end into static_cache_. The data | |
| 142 // in this buffer is also used when the data in the central directory is | |
|
mtomasz
2017/04/10 07:15:09
Is size of this cache enough for large ZIP files,
takise
2017/04/11 06:00:52
Actually, this buffer doesn't have 'central direct
mtomasz
2017/04/11 06:36:45
Thanks for the explanation. Now I understand very
| |
| 143 // requested by MiniZip later. | |
| 144 char static_cache_[volume_archive_constants::kStaticCacheSize]; | |
| 145 | |
| 146 // The offset from which static_cache_ has the data of the archive. | |
| 147 int64_t static_cache_offset_; | |
| 148 | |
| 149 // The size of the data in static_cache_. | |
| 150 int64_t static_cache_size_; | |
| 91 | 151 |
| 92 // The data offset, which will be offset + length after last read | 152 // The data offset, which will be offset + length after last read |
| 93 // operation, where offset and length are method parameters for | 153 // operation, where offset and length are method parameters for |
| 94 // VolumeArchiveLibarchive::ReadData. Data offset is used to improve | 154 // VolumeArchiveLibarchive::ReadData. Data offset is used to improve |
| 95 // performance for consecutive calls to VolumeArchiveLibarchive::ReadData. | 155 // performance for consecutive calls to VolumeArchiveLibarchive::ReadData. |
| 96 // | 156 // |
| 97 // Intead of starting the read from the beginning for every | 157 // Intead of starting the read from the beginning for every |
| 98 // VolumeArchiveLibarchive::ReadData, the next call will start | 158 // VolumeArchiveLibarchive::ReadData, the next call will start |
| 99 // from last_read_data_offset_ in case the offset parameter of | 159 // from last_read_data_offset_ in case the offset parameter of |
| 100 // VolumeArchiveLibarchive::ReadData has the same value as | 160 // VolumeArchiveLibarchive::ReadData has the same value as |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 128 | 188 |
| 129 // The size of valid data starting from decompressed_data_ that is stored | 189 // The size of valid data starting from decompressed_data_ that is stored |
| 130 // inside decompressed_data_buffer_. | 190 // inside decompressed_data_buffer_. |
| 131 int64_t decompressed_data_size_; | 191 int64_t decompressed_data_size_; |
| 132 | 192 |
| 133 // True if VolumeArchiveLibarchive::DecompressData failed. | 193 // True if VolumeArchiveLibarchive::DecompressData failed. |
| 134 bool decompressed_error_; | 194 bool decompressed_error_; |
| 135 }; | 195 }; |
| 136 | 196 |
| 137 #endif // VOLUME_ARCHIVE_LIBARCHIVE_H_ | 197 #endif // VOLUME_ARCHIVE_LIBARCHIVE_H_ |
| OLD | NEW |