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