OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef VOLUME_ARCHIVE_LIBARCHIVE_H_ | |
6 #define VOLUME_ARCHIVE_LIBARCHIVE_H_ | |
7 | |
8 #include <string> | |
9 | |
10 #include "archive.h" | |
11 | |
12 #include "volume_archive.h" | |
13 | |
14 // A namespace with constants used by VolumeArchiveLibarchive. | |
15 namespace volume_archive_constants { | |
16 | |
17 const char kArchiveReadNewError[] = "Could not allocate archive."; | |
18 const char kFileNotFound[] = "File not found for read data request."; | |
19 const char kVolumeReaderError[] = "VolumeReader failed to retrieve data."; | |
20 const char kArchiveSupportErrorPrefix[] = "Error at support rar/zip format: "; | |
21 const char kArchiveOpenErrorPrefix[] = "Error at open archive: "; | |
22 const char kArchiveNextHeaderErrorPrefix[] = | |
23 "Error at reading next header for metadata: "; | |
24 const char kArchiveReadDataErrorPrefix[] = "Error at reading data: "; | |
25 const char kArchiveReadFreeErrorPrefix[] = "Error at archive free: "; | |
26 | |
27 // The size of the buffer used to skip unnecessary data. | |
28 // Should be positive and less than size_t maximum. | |
29 const int64_t kDummyBufferSize = 512 * 1024; // 512 KB | |
30 | |
31 // The size of the buffer used by ReadInProgress to decompress data. | |
32 // Should be positive and less than size_t maximum. | |
33 const int64_t kDecompressBufferSize = 512 * 1024; // 512 KB. | |
34 | |
35 // The maximum data chunk size for VolumeReader::Read requests. | |
36 // Should be positive. | |
37 const int64_t kMaximumDataChunkSize = 512 * 1024; // 512 KB. | |
38 | |
39 // The minimum data chunk size for VolumeReader::Read requests. | |
40 // Should be positive. | |
41 const int64_t kMinimumDataChunkSize = 32 * 1024; // 16 KB. | |
42 | |
43 } // namespace volume_archive_constants | |
44 | |
45 // Defines an implementation of VolumeArchive that wraps all libarchive | |
46 // operations. | |
47 class VolumeArchiveLibarchive : public VolumeArchive { | |
48 public: | |
49 explicit VolumeArchiveLibarchive(VolumeReader* reader); | |
50 | |
51 virtual ~VolumeArchiveLibarchive(); | |
52 | |
53 // See volume_archive_interface.h. | |
54 virtual bool Init(const std::string& encoding); | |
55 | |
56 // See volume_archive_interface.h. | |
57 virtual Result GetNextHeader(); | |
58 virtual Result GetNextHeader(const char** path_name, | |
59 int64_t* size, | |
60 bool* is_directory, | |
61 time_t* modification_time); | |
62 | |
63 // See volume_archive_interface.h. | |
64 virtual bool SeekHeader(int64_t index); | |
65 | |
66 // See volume_archive_interface.h. | |
67 virtual int64_t ReadData(int64_t offset, | |
68 int64_t length, | |
69 const char** buffer); | |
70 | |
71 // See volume_archive_interface.h. | |
72 virtual void MaybeDecompressAhead(); | |
73 | |
74 // See volume_archive_interface.h. | |
75 virtual bool Cleanup(); | |
76 | |
77 int64_t reader_data_size() const { return reader_data_size_; } | |
78 | |
79 private: | |
80 // Decompress length bytes of data starting from offset. | |
81 void DecompressData(int64_t offset, int64_t length); | |
82 | |
83 // The size of the requested data from VolumeReader. | |
84 int64_t reader_data_size_; | |
85 | |
86 // The libarchive correspondent archive object. | |
87 archive* archive_; | |
88 | |
89 // The last reached entry with VolumeArchiveLibarchive::GetNextHeader. | |
90 archive_entry* current_archive_entry_; | |
91 | |
92 // The data offset, which will be offset + length after last read | |
93 // operation, where offset and length are method parameters for | |
94 // VolumeArchiveLibarchive::ReadData. Data offset is used to improve | |
95 // performance for consecutive calls to VolumeArchiveLibarchive::ReadData. | |
96 // | |
97 // Intead of starting the read from the beginning for every | |
98 // VolumeArchiveLibarchive::ReadData, the next call will start | |
99 // from last_read_data_offset_ in case the offset parameter of | |
100 // VolumeArchiveLibarchive::ReadData has the same value as | |
101 // last_read_data_offset_. This avoids decompressing again the bytes at | |
102 // the begninning of the file, which is the average case scenario. | |
103 // But in case the offset parameter is different than last_read_data_offset_, | |
104 // then dummy_buffer_ will be used to ignore unused bytes. | |
105 int64_t last_read_data_offset_; | |
106 | |
107 // The length of the last VolumeArchiveLibarchive::ReadData. Used for | |
108 // decompress ahead. | |
109 int64_t last_read_data_length_; | |
110 | |
111 // Dummy buffer for unused data read using VolumeArchiveLibarchive::ReadData. | |
112 // Sometimes VolumeArchiveLibarchive::ReadData can require reading from | |
113 // offsets different from last_read_data_offset_. In this case some bytes | |
114 // must be skipped. Because seeking is not possible inside compressed files, | |
115 // the bytes will be discarded using this buffer. | |
116 char dummy_buffer_[volume_archive_constants::kDummyBufferSize]; | |
117 | |
118 // The address where the decompressed data starting from | |
119 // decompressed_offset_ is stored. It should point to a valid location | |
120 // inside decompressed_data_buffer_. Necesssary in order to NOT throw | |
121 // away unused decompressed bytes as throwing them away would mean in some | |
122 // situations restarting decompressing the file from the beginning. | |
123 char* decompressed_data_; | |
124 | |
125 // The actual buffer that contains the decompressed data. | |
126 char decompressed_data_buffer_ | |
127 [volume_archive_constants::kDecompressBufferSize]; | |
128 | |
129 // The size of valid data starting from decompressed_data_ that is stored | |
130 // inside decompressed_data_buffer_. | |
131 int64_t decompressed_data_size_; | |
132 | |
133 // True if VolumeArchiveLibarchive::DecompressData failed. | |
134 bool decompressed_error_; | |
135 }; | |
136 | |
137 #endif // VOLUME_ARCHIVE_LIBARCHIVE_H_ | |
OLD | NEW |