1*288bf522SAndroid Build Coastguard Worker #include "meminspect.h"
2*288bf522SAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
3*288bf522SAndroid Build Coastguard Worker #include "ziparchive/zip_archive.h"
4*288bf522SAndroid Build Coastguard Worker
5*288bf522SAndroid Build Coastguard Worker using namespace std;
6*288bf522SAndroid Build Coastguard Worker using namespace android::base;
7*288bf522SAndroid Build Coastguard Worker using namespace ::android::base;
8*288bf522SAndroid Build Coastguard Worker
9*288bf522SAndroid Build Coastguard Worker const static VmaRange VMA_RANGE_EMPTY = VmaRange(0, 0);
10*288bf522SAndroid Build Coastguard Worker
end_offset() const11*288bf522SAndroid Build Coastguard Worker uint32_t VmaRange::end_offset() const {
12*288bf522SAndroid Build Coastguard Worker return offset + length;
13*288bf522SAndroid Build Coastguard Worker }
14*288bf522SAndroid Build Coastguard Worker
compute_total_size()15*288bf522SAndroid Build Coastguard Worker uint64_t VmaRangeGroup::compute_total_size() {
16*288bf522SAndroid Build Coastguard Worker uint64_t total_size = 0;
17*288bf522SAndroid Build Coastguard Worker for (auto&& range : ranges) {
18*288bf522SAndroid Build Coastguard Worker total_size += range.length;
19*288bf522SAndroid Build Coastguard Worker }
20*288bf522SAndroid Build Coastguard Worker return total_size;
21*288bf522SAndroid Build Coastguard Worker }
22*288bf522SAndroid Build Coastguard Worker
apply_offset(uint64_t offset)23*288bf522SAndroid Build Coastguard Worker void VmaRangeGroup::apply_offset(uint64_t offset) {
24*288bf522SAndroid Build Coastguard Worker for (auto&& range : ranges) {
25*288bf522SAndroid Build Coastguard Worker range.offset += offset;
26*288bf522SAndroid Build Coastguard Worker }
27*288bf522SAndroid Build Coastguard Worker }
28*288bf522SAndroid Build Coastguard Worker
compute_coverage(const VmaRange & range,VmaRangeGroup & out_memres) const29*288bf522SAndroid Build Coastguard Worker void VmaRangeGroup::compute_coverage(const VmaRange& range, VmaRangeGroup& out_memres) const {
30*288bf522SAndroid Build Coastguard Worker for (auto&& resident_range : ranges) {
31*288bf522SAndroid Build Coastguard Worker VmaRange intersect_res = resident_range.intersect(range);
32*288bf522SAndroid Build Coastguard Worker if (!intersect_res.is_empty()) {
33*288bf522SAndroid Build Coastguard Worker out_memres.ranges.push_back(intersect_res);
34*288bf522SAndroid Build Coastguard Worker }
35*288bf522SAndroid Build Coastguard Worker }
36*288bf522SAndroid Build Coastguard Worker }
37*288bf522SAndroid Build Coastguard Worker
is_empty() const38*288bf522SAndroid Build Coastguard Worker bool VmaRange::is_empty() const {
39*288bf522SAndroid Build Coastguard Worker return length == 0;
40*288bf522SAndroid Build Coastguard Worker }
41*288bf522SAndroid Build Coastguard Worker
intersect(const VmaRange & target) const42*288bf522SAndroid Build Coastguard Worker VmaRange VmaRange::intersect(const VmaRange& target) const {
43*288bf522SAndroid Build Coastguard Worker // First check if the slice is outside our range
44*288bf522SAndroid Build Coastguard Worker if (target.end_offset() <= this->offset) {
45*288bf522SAndroid Build Coastguard Worker return VMA_RANGE_EMPTY;
46*288bf522SAndroid Build Coastguard Worker }
47*288bf522SAndroid Build Coastguard Worker if (target.offset >= this->end_offset()) {
48*288bf522SAndroid Build Coastguard Worker return VMA_RANGE_EMPTY;
49*288bf522SAndroid Build Coastguard Worker }
50*288bf522SAndroid Build Coastguard Worker VmaRange result;
51*288bf522SAndroid Build Coastguard Worker // the slice should now be inside the range so compute the intersection.
52*288bf522SAndroid Build Coastguard Worker result.offset = std::max(target.offset, this->offset);
53*288bf522SAndroid Build Coastguard Worker uint32_t res_end = std::min(target.end_offset(), end_offset());
54*288bf522SAndroid Build Coastguard Worker result.length = res_end - result.offset;
55*288bf522SAndroid Build Coastguard Worker
56*288bf522SAndroid Build Coastguard Worker return result;
57*288bf522SAndroid Build Coastguard Worker }
58*288bf522SAndroid Build Coastguard Worker
union_merge(const VmaRange & target) const59*288bf522SAndroid Build Coastguard Worker VmaRange VmaRange::union_merge(const VmaRange& target) const {
60*288bf522SAndroid Build Coastguard Worker VmaRange result = intersect(target);
61*288bf522SAndroid Build Coastguard Worker if (result.is_empty()) {
62*288bf522SAndroid Build Coastguard Worker // Disjointed ranges, no merge.
63*288bf522SAndroid Build Coastguard Worker return VMA_RANGE_EMPTY;
64*288bf522SAndroid Build Coastguard Worker }
65*288bf522SAndroid Build Coastguard Worker
66*288bf522SAndroid Build Coastguard Worker // Since there is an intersection, merge ranges between lowest
67*288bf522SAndroid Build Coastguard Worker // and highest value.
68*288bf522SAndroid Build Coastguard Worker result.offset = std::min(offset, target.offset);
69*288bf522SAndroid Build Coastguard Worker uint32_t res_end = std::max(target.end_offset(), end_offset());
70*288bf522SAndroid Build Coastguard Worker result.length = res_end - result.offset;
71*288bf522SAndroid Build Coastguard Worker return result;
72*288bf522SAndroid Build Coastguard Worker }
73*288bf522SAndroid Build Coastguard Worker
align_ranges(std::vector<VmaRange> & vmas_to_align,unsigned int alignment)74*288bf522SAndroid Build Coastguard Worker void align_ranges(std::vector<VmaRange>& vmas_to_align, unsigned int alignment) {
75*288bf522SAndroid Build Coastguard Worker for (auto&& vma_to_align : vmas_to_align) {
76*288bf522SAndroid Build Coastguard Worker uint32_t unaligned_offset = vma_to_align.offset % alignment;
77*288bf522SAndroid Build Coastguard Worker vma_to_align.offset -= unaligned_offset;
78*288bf522SAndroid Build Coastguard Worker vma_to_align.length += unaligned_offset;
79*288bf522SAndroid Build Coastguard Worker }
80*288bf522SAndroid Build Coastguard Worker }
81*288bf522SAndroid Build Coastguard Worker
compare_range(VmaRange & a,VmaRange & b)82*288bf522SAndroid Build Coastguard Worker bool compare_range(VmaRange& a, VmaRange& b) {
83*288bf522SAndroid Build Coastguard Worker return a.offset < b.offset;
84*288bf522SAndroid Build Coastguard Worker }
85*288bf522SAndroid Build Coastguard Worker
merge_ranges(const std::vector<VmaRange> & ranges)86*288bf522SAndroid Build Coastguard Worker std::vector<VmaRange> merge_ranges(const std::vector<VmaRange>& ranges) {
87*288bf522SAndroid Build Coastguard Worker if (ranges.size() <= 1) {
88*288bf522SAndroid Build Coastguard Worker // Not enough ranges to perform a merge.
89*288bf522SAndroid Build Coastguard Worker return ranges;
90*288bf522SAndroid Build Coastguard Worker }
91*288bf522SAndroid Build Coastguard Worker
92*288bf522SAndroid Build Coastguard Worker std::vector<VmaRange> to_merge_ranges = ranges;
93*288bf522SAndroid Build Coastguard Worker std::vector<VmaRange> merged_ranges;
94*288bf522SAndroid Build Coastguard Worker // Sort the ranges to make a slightly more efficient merging.
95*288bf522SAndroid Build Coastguard Worker std::sort(to_merge_ranges.begin(), to_merge_ranges.end(), compare_range);
96*288bf522SAndroid Build Coastguard Worker
97*288bf522SAndroid Build Coastguard Worker // The first element will always start as-is, then start merging with subsequent elements.
98*288bf522SAndroid Build Coastguard Worker merged_ranges.push_back(to_merge_ranges[0]);
99*288bf522SAndroid Build Coastguard Worker for (int iMerged = 0, iTarget = 1; iTarget < to_merge_ranges.size(); ++iTarget) {
100*288bf522SAndroid Build Coastguard Worker VmaRange merged = merged_ranges[iMerged].union_merge(to_merge_ranges[iTarget]);
101*288bf522SAndroid Build Coastguard Worker if (!merged.is_empty()) {
102*288bf522SAndroid Build Coastguard Worker // Merge was successful, swallow range.
103*288bf522SAndroid Build Coastguard Worker merged_ranges[iMerged] = merged;
104*288bf522SAndroid Build Coastguard Worker } else {
105*288bf522SAndroid Build Coastguard Worker // Merge failed, add disjointed range.
106*288bf522SAndroid Build Coastguard Worker merged_ranges.push_back(to_merge_ranges[iTarget]);
107*288bf522SAndroid Build Coastguard Worker ++iMerged;
108*288bf522SAndroid Build Coastguard Worker }
109*288bf522SAndroid Build Coastguard Worker }
110*288bf522SAndroid Build Coastguard Worker
111*288bf522SAndroid Build Coastguard Worker return merged_ranges;
112*288bf522SAndroid Build Coastguard Worker }
113*288bf522SAndroid Build Coastguard Worker
get_file_size(const std::string & file)114*288bf522SAndroid Build Coastguard Worker int64_t get_file_size(const std::string& file) {
115*288bf522SAndroid Build Coastguard Worker unique_fd file_ufd(open(file.c_str(), O_RDONLY));
116*288bf522SAndroid Build Coastguard Worker int fd = file_ufd.get();
117*288bf522SAndroid Build Coastguard Worker if (fd == -1) {
118*288bf522SAndroid Build Coastguard Worker return -1;
119*288bf522SAndroid Build Coastguard Worker }
120*288bf522SAndroid Build Coastguard Worker
121*288bf522SAndroid Build Coastguard Worker struct stat fstat_res;
122*288bf522SAndroid Build Coastguard Worker int res = fstat(fd, &fstat_res);
123*288bf522SAndroid Build Coastguard Worker if (res == -1) {
124*288bf522SAndroid Build Coastguard Worker return -1;
125*288bf522SAndroid Build Coastguard Worker }
126*288bf522SAndroid Build Coastguard Worker
127*288bf522SAndroid Build Coastguard Worker return fstat_res.st_size;
128*288bf522SAndroid Build Coastguard Worker }
129*288bf522SAndroid Build Coastguard Worker
probe_resident_memory(string probed_file,VmaRangeGroup & resident_ranges,int pages_per_mincore)130*288bf522SAndroid Build Coastguard Worker int probe_resident_memory(string probed_file,
131*288bf522SAndroid Build Coastguard Worker /*out*/ VmaRangeGroup& resident_ranges, int pages_per_mincore) {
132*288bf522SAndroid Build Coastguard Worker unique_fd probed_file_ufd(open(probed_file.c_str(), O_RDONLY));
133*288bf522SAndroid Build Coastguard Worker int probe_fd = probed_file_ufd.get();
134*288bf522SAndroid Build Coastguard Worker if (probe_fd == -1) {
135*288bf522SAndroid Build Coastguard Worker return MEMINSPECT_FAIL_OPEN;
136*288bf522SAndroid Build Coastguard Worker }
137*288bf522SAndroid Build Coastguard Worker
138*288bf522SAndroid Build Coastguard Worker int64_t total_bytes = get_file_size(probed_file);
139*288bf522SAndroid Build Coastguard Worker if (total_bytes < 0) {
140*288bf522SAndroid Build Coastguard Worker return MEMINSPECT_FAIL_FSTAT;
141*288bf522SAndroid Build Coastguard Worker }
142*288bf522SAndroid Build Coastguard Worker
143*288bf522SAndroid Build Coastguard Worker char* base_address =
144*288bf522SAndroid Build Coastguard Worker (char*)mmap(0, (uint64_t)total_bytes, PROT_READ, MAP_SHARED, probe_fd, /*offset*/ 0);
145*288bf522SAndroid Build Coastguard Worker
146*288bf522SAndroid Build Coastguard Worker // this determines how many pages to inspect per mincore syscall
147*288bf522SAndroid Build Coastguard Worker unsigned char* window = new unsigned char[pages_per_mincore];
148*288bf522SAndroid Build Coastguard Worker
149*288bf522SAndroid Build Coastguard Worker unsigned int page_size = sysconf(_SC_PAGESIZE);
150*288bf522SAndroid Build Coastguard Worker unsigned long bytes_inspected = 0;
151*288bf522SAndroid Build Coastguard Worker
152*288bf522SAndroid Build Coastguard Worker // total bytes in inspection window
153*288bf522SAndroid Build Coastguard Worker unsigned long window_bytes = page_size * pages_per_mincore;
154*288bf522SAndroid Build Coastguard Worker
155*288bf522SAndroid Build Coastguard Worker char* window_base;
156*288bf522SAndroid Build Coastguard Worker bool started_vma_range = false;
157*288bf522SAndroid Build Coastguard Worker uint32_t resident_vma_start_offset = 0;
158*288bf522SAndroid Build Coastguard Worker for (window_base = base_address; bytes_inspected < total_bytes;
159*288bf522SAndroid Build Coastguard Worker window_base += window_bytes, bytes_inspected += window_bytes) {
160*288bf522SAndroid Build Coastguard Worker int res = mincore(window_base, window_bytes, window);
161*288bf522SAndroid Build Coastguard Worker if (res != 0) {
162*288bf522SAndroid Build Coastguard Worker if (errno == ENOMEM) {
163*288bf522SAndroid Build Coastguard Worker // Did not find page, maybe it's a hole.
164*288bf522SAndroid Build Coastguard Worker continue;
165*288bf522SAndroid Build Coastguard Worker }
166*288bf522SAndroid Build Coastguard Worker return MEMINSPECT_FAIL_MINCORE;
167*288bf522SAndroid Build Coastguard Worker }
168*288bf522SAndroid Build Coastguard Worker // Inspect the provided mincore window result sequentially
169*288bf522SAndroid Build Coastguard Worker // and as soon as a change in residency happens a range is
170*288bf522SAndroid Build Coastguard Worker // created or finished.
171*288bf522SAndroid Build Coastguard Worker for (int iWin = 0; iWin < pages_per_mincore; ++iWin) {
172*288bf522SAndroid Build Coastguard Worker if ((window[iWin] & (unsigned char)1) != 0) {
173*288bf522SAndroid Build Coastguard Worker // Page is resident
174*288bf522SAndroid Build Coastguard Worker if (!started_vma_range) {
175*288bf522SAndroid Build Coastguard Worker // End of range
176*288bf522SAndroid Build Coastguard Worker started_vma_range = true;
177*288bf522SAndroid Build Coastguard Worker uint32_t window_offset = iWin * page_size;
178*288bf522SAndroid Build Coastguard Worker resident_vma_start_offset = window_base + window_offset - base_address;
179*288bf522SAndroid Build Coastguard Worker }
180*288bf522SAndroid Build Coastguard Worker } else {
181*288bf522SAndroid Build Coastguard Worker // Page is not resident
182*288bf522SAndroid Build Coastguard Worker if (started_vma_range) {
183*288bf522SAndroid Build Coastguard Worker // Start of range
184*288bf522SAndroid Build Coastguard Worker started_vma_range = false;
185*288bf522SAndroid Build Coastguard Worker uint32_t window_offset = iWin * page_size;
186*288bf522SAndroid Build Coastguard Worker uint32_t resident_vma_end_offset = window_base + window_offset - base_address;
187*288bf522SAndroid Build Coastguard Worker uint32_t resident_len = resident_vma_end_offset - resident_vma_start_offset;
188*288bf522SAndroid Build Coastguard Worker VmaRange vma_range(resident_vma_start_offset, resident_len);
189*288bf522SAndroid Build Coastguard Worker resident_ranges.ranges.push_back(vma_range);
190*288bf522SAndroid Build Coastguard Worker }
191*288bf522SAndroid Build Coastguard Worker }
192*288bf522SAndroid Build Coastguard Worker }
193*288bf522SAndroid Build Coastguard Worker }
194*288bf522SAndroid Build Coastguard Worker // This was the last window, so close any opened vma range
195*288bf522SAndroid Build Coastguard Worker if (started_vma_range) {
196*288bf522SAndroid Build Coastguard Worker started_vma_range = false;
197*288bf522SAndroid Build Coastguard Worker uint32_t in_memory_vma_end = window_base - base_address;
198*288bf522SAndroid Build Coastguard Worker uint32_t resident_len = in_memory_vma_end - resident_vma_start_offset;
199*288bf522SAndroid Build Coastguard Worker VmaRange vma_range(resident_vma_start_offset, resident_len);
200*288bf522SAndroid Build Coastguard Worker resident_ranges.ranges.push_back(vma_range);
201*288bf522SAndroid Build Coastguard Worker }
202*288bf522SAndroid Build Coastguard Worker
203*288bf522SAndroid Build Coastguard Worker return 0;
204*288bf522SAndroid Build Coastguard Worker }
205*288bf522SAndroid Build Coastguard Worker
~ZipMemInspector()206*288bf522SAndroid Build Coastguard Worker ZipMemInspector::~ZipMemInspector() {
207*288bf522SAndroid Build Coastguard Worker CloseArchive(handle_);
208*288bf522SAndroid Build Coastguard Worker delete probe_resident_;
209*288bf522SAndroid Build Coastguard Worker }
210*288bf522SAndroid Build Coastguard Worker
compute_coverage(const VmaRangeGroup & probe) const211*288bf522SAndroid Build Coastguard Worker ZipEntryCoverage ZipEntryCoverage::compute_coverage(const VmaRangeGroup& probe) const {
212*288bf522SAndroid Build Coastguard Worker ZipEntryCoverage file_coverage;
213*288bf522SAndroid Build Coastguard Worker file_coverage.info = info;
214*288bf522SAndroid Build Coastguard Worker
215*288bf522SAndroid Build Coastguard Worker // Compute coverage for each range in file against probe which represents a set of ranges.
216*288bf522SAndroid Build Coastguard Worker for (auto&& range : coverage.ranges) {
217*288bf522SAndroid Build Coastguard Worker probe.compute_coverage(range, file_coverage.coverage);
218*288bf522SAndroid Build Coastguard Worker }
219*288bf522SAndroid Build Coastguard Worker
220*288bf522SAndroid Build Coastguard Worker return file_coverage;
221*288bf522SAndroid Build Coastguard Worker }
222*288bf522SAndroid Build Coastguard Worker
compute_coverage(const std::vector<ZipEntryCoverage> & files,VmaRangeGroup * probe)223*288bf522SAndroid Build Coastguard Worker std::vector<ZipEntryCoverage> ZipMemInspector::compute_coverage(
224*288bf522SAndroid Build Coastguard Worker const std::vector<ZipEntryCoverage>& files, VmaRangeGroup* probe) {
225*288bf522SAndroid Build Coastguard Worker if (probe == nullptr) {
226*288bf522SAndroid Build Coastguard Worker // No probe to calculate coverage against, so coverage is zero.
227*288bf522SAndroid Build Coastguard Worker return std::vector<ZipEntryCoverage>();
228*288bf522SAndroid Build Coastguard Worker }
229*288bf522SAndroid Build Coastguard Worker
230*288bf522SAndroid Build Coastguard Worker std::vector<ZipEntryCoverage> file_coverages;
231*288bf522SAndroid Build Coastguard Worker // Find the file coverage against provided probe.
232*288bf522SAndroid Build Coastguard Worker for (auto&& file : files) {
233*288bf522SAndroid Build Coastguard Worker // For each file, compute coverage against the probe which represents a list of ranges.
234*288bf522SAndroid Build Coastguard Worker ZipEntryCoverage file_coverage = file.compute_coverage(*probe);
235*288bf522SAndroid Build Coastguard Worker file_coverages.push_back(file_coverage);
236*288bf522SAndroid Build Coastguard Worker }
237*288bf522SAndroid Build Coastguard Worker
238*288bf522SAndroid Build Coastguard Worker return file_coverages;
239*288bf522SAndroid Build Coastguard Worker }
240*288bf522SAndroid Build Coastguard Worker
add_file_info(ZipEntryInfo & file)241*288bf522SAndroid Build Coastguard Worker void ZipMemInspector::add_file_info(ZipEntryInfo& file) {
242*288bf522SAndroid Build Coastguard Worker entry_infos_.push_back(file);
243*288bf522SAndroid Build Coastguard Worker }
244*288bf522SAndroid Build Coastguard Worker
compute_per_file_coverage()245*288bf522SAndroid Build Coastguard Worker int ZipMemInspector::compute_per_file_coverage() {
246*288bf522SAndroid Build Coastguard Worker if (entry_infos_.empty()) {
247*288bf522SAndroid Build Coastguard Worker // We haven't read the file information yet, so do it now.
248*288bf522SAndroid Build Coastguard Worker if (read_files_and_offsets()) {
249*288bf522SAndroid Build Coastguard Worker cerr << "Could not read zip entries to compute coverages." << endl;
250*288bf522SAndroid Build Coastguard Worker return 1;
251*288bf522SAndroid Build Coastguard Worker }
252*288bf522SAndroid Build Coastguard Worker }
253*288bf522SAndroid Build Coastguard Worker
254*288bf522SAndroid Build Coastguard Worker // All existing files should consider their whole memory as present by default.
255*288bf522SAndroid Build Coastguard Worker std::vector<ZipEntryCoverage> entry_coverages;
256*288bf522SAndroid Build Coastguard Worker for (auto&& entry_info : entry_infos_) {
257*288bf522SAndroid Build Coastguard Worker ZipEntryCoverage entry_coverage;
258*288bf522SAndroid Build Coastguard Worker entry_coverage.info = entry_info;
259*288bf522SAndroid Build Coastguard Worker VmaRange file_vma_range(entry_info.offset_in_zip, entry_info.file_size_bytes);
260*288bf522SAndroid Build Coastguard Worker entry_coverage.coverage.ranges.push_back(file_vma_range);
261*288bf522SAndroid Build Coastguard Worker entry_coverage.coverage.compute_total_size();
262*288bf522SAndroid Build Coastguard Worker entry_coverages.push_back(entry_coverage);
263*288bf522SAndroid Build Coastguard Worker }
264*288bf522SAndroid Build Coastguard Worker
265*288bf522SAndroid Build Coastguard Worker if (probe_resident_ != nullptr) {
266*288bf522SAndroid Build Coastguard Worker // We decided to compute coverage based on a probe
267*288bf522SAndroid Build Coastguard Worker entry_coverages_ = compute_coverage(entry_coverages, probe_resident_);
268*288bf522SAndroid Build Coastguard Worker } else {
269*288bf522SAndroid Build Coastguard Worker // No probe means whole file coverage
270*288bf522SAndroid Build Coastguard Worker entry_coverages_ = entry_coverages;
271*288bf522SAndroid Build Coastguard Worker }
272*288bf522SAndroid Build Coastguard Worker
273*288bf522SAndroid Build Coastguard Worker return 0;
274*288bf522SAndroid Build Coastguard Worker }
275*288bf522SAndroid Build Coastguard Worker
get_probe()276*288bf522SAndroid Build Coastguard Worker VmaRangeGroup* ZipMemInspector::get_probe() {
277*288bf522SAndroid Build Coastguard Worker return probe_resident_;
278*288bf522SAndroid Build Coastguard Worker }
279*288bf522SAndroid Build Coastguard Worker
set_existing_probe(VmaRangeGroup * probe)280*288bf522SAndroid Build Coastguard Worker void ZipMemInspector::set_existing_probe(VmaRangeGroup* probe) {
281*288bf522SAndroid Build Coastguard Worker this->probe_resident_ = probe;
282*288bf522SAndroid Build Coastguard Worker }
283*288bf522SAndroid Build Coastguard Worker
get_file_coverages()284*288bf522SAndroid Build Coastguard Worker std::vector<ZipEntryCoverage>& ZipMemInspector::get_file_coverages() {
285*288bf522SAndroid Build Coastguard Worker return entry_coverages_;
286*288bf522SAndroid Build Coastguard Worker }
287*288bf522SAndroid Build Coastguard Worker
probe_resident()288*288bf522SAndroid Build Coastguard Worker int ZipMemInspector::probe_resident() {
289*288bf522SAndroid Build Coastguard Worker probe_resident_ = new VmaRangeGroup();
290*288bf522SAndroid Build Coastguard Worker int res = probe_resident_memory(filename_, *probe_resident_);
291*288bf522SAndroid Build Coastguard Worker if (res != 0) {
292*288bf522SAndroid Build Coastguard Worker // Failed to probe
293*288bf522SAndroid Build Coastguard Worker return res;
294*288bf522SAndroid Build Coastguard Worker }
295*288bf522SAndroid Build Coastguard Worker
296*288bf522SAndroid Build Coastguard Worker return 0;
297*288bf522SAndroid Build Coastguard Worker }
298*288bf522SAndroid Build Coastguard Worker
get_file_infos()299*288bf522SAndroid Build Coastguard Worker std::vector<ZipEntryInfo>& ZipMemInspector::get_file_infos() {
300*288bf522SAndroid Build Coastguard Worker return entry_infos_;
301*288bf522SAndroid Build Coastguard Worker }
302*288bf522SAndroid Build Coastguard Worker
read_files_and_offsets()303*288bf522SAndroid Build Coastguard Worker int ZipMemInspector::read_files_and_offsets() {
304*288bf522SAndroid Build Coastguard Worker if (OpenArchive(filename_.c_str(), &handle_) < 0) {
305*288bf522SAndroid Build Coastguard Worker return 1;
306*288bf522SAndroid Build Coastguard Worker }
307*288bf522SAndroid Build Coastguard Worker void* cookie;
308*288bf522SAndroid Build Coastguard Worker int res = StartIteration(handle_, &cookie);
309*288bf522SAndroid Build Coastguard Worker if (res != 0) {
310*288bf522SAndroid Build Coastguard Worker return 1;
311*288bf522SAndroid Build Coastguard Worker }
312*288bf522SAndroid Build Coastguard Worker
313*288bf522SAndroid Build Coastguard Worker ZipEntry64 entry;
314*288bf522SAndroid Build Coastguard Worker string name;
315*288bf522SAndroid Build Coastguard Worker while (Next(cookie, &entry, &name) == 0) {
316*288bf522SAndroid Build Coastguard Worker ZipEntryInfo file;
317*288bf522SAndroid Build Coastguard Worker file.name = name;
318*288bf522SAndroid Build Coastguard Worker file.offset_in_zip = entry.offset;
319*288bf522SAndroid Build Coastguard Worker file.file_size_bytes = entry.compressed_length;
320*288bf522SAndroid Build Coastguard Worker file.uncompressed_size = entry.uncompressed_length;
321*288bf522SAndroid Build Coastguard Worker entry_infos_.push_back(file);
322*288bf522SAndroid Build Coastguard Worker }
323*288bf522SAndroid Build Coastguard Worker return 0;
324*288bf522SAndroid Build Coastguard Worker }
325