• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2020 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include <sys/types.h>
18 #include <unistd.h>
19 
20 #include <limits>
21 #include <optional>
22 #include <set>
23 #include <unordered_map>
24 #include <unordered_set>
25 #include <vector>
26 
27 #include <android-base/file.h>
28 #include <android-base/logging.h>
29 #include <libsnapshot/cow_reader.h>
30 #include <zlib.h>
31 
32 #include "cow_decompress.h"
33 
34 namespace android {
35 namespace snapshot {
36 
CowReader(ReaderFlags reader_flag)37 CowReader::CowReader(ReaderFlags reader_flag)
38     : fd_(-1),
39       header_(),
40       fd_size_(0),
41       block_pos_index_(std::make_shared<std::vector<int>>()),
42       reader_flag_(reader_flag) {}
43 
SHA256(const void *,size_t,uint8_t[])44 static void SHA256(const void*, size_t, uint8_t[]) {
45 #if 0
46     SHA256_CTX c;
47     SHA256_Init(&c);
48     SHA256_Update(&c, data, length);
49     SHA256_Final(out, &c);
50 #endif
51 }
52 
CloneCowReader()53 std::unique_ptr<CowReader> CowReader::CloneCowReader() {
54     auto cow = std::make_unique<CowReader>();
55     cow->owned_fd_.reset();
56     cow->header_ = header_;
57     cow->footer_ = footer_;
58     cow->fd_size_ = fd_size_;
59     cow->last_label_ = last_label_;
60     cow->ops_ = ops_;
61     cow->merge_op_start_ = merge_op_start_;
62     cow->num_total_data_ops_ = num_total_data_ops_;
63     cow->num_ordered_ops_to_merge_ = num_ordered_ops_to_merge_;
64     cow->has_seq_ops_ = has_seq_ops_;
65     cow->data_loc_ = data_loc_;
66     cow->block_pos_index_ = block_pos_index_;
67     return cow;
68 }
69 
InitForMerge(android::base::unique_fd && fd)70 bool CowReader::InitForMerge(android::base::unique_fd&& fd) {
71     owned_fd_ = std::move(fd);
72     fd_ = owned_fd_.get();
73 
74     auto pos = lseek(fd_.get(), 0, SEEK_END);
75     if (pos < 0) {
76         PLOG(ERROR) << "lseek end failed";
77         return false;
78     }
79     fd_size_ = pos;
80 
81     if (lseek(fd_.get(), 0, SEEK_SET) < 0) {
82         PLOG(ERROR) << "lseek header failed";
83         return false;
84     }
85     if (!android::base::ReadFully(fd_, &header_, sizeof(header_))) {
86         PLOG(ERROR) << "read header failed";
87         return false;
88     }
89 
90     return true;
91 }
92 
Parse(android::base::unique_fd && fd,std::optional<uint64_t> label)93 bool CowReader::Parse(android::base::unique_fd&& fd, std::optional<uint64_t> label) {
94     owned_fd_ = std::move(fd);
95     return Parse(android::base::borrowed_fd{owned_fd_}, label);
96 }
97 
Parse(android::base::borrowed_fd fd,std::optional<uint64_t> label)98 bool CowReader::Parse(android::base::borrowed_fd fd, std::optional<uint64_t> label) {
99     fd_ = fd;
100 
101     auto pos = lseek(fd_.get(), 0, SEEK_END);
102     if (pos < 0) {
103         PLOG(ERROR) << "lseek end failed";
104         return false;
105     }
106     fd_size_ = pos;
107 
108     if (lseek(fd_.get(), 0, SEEK_SET) < 0) {
109         PLOG(ERROR) << "lseek header failed";
110         return false;
111     }
112     if (!android::base::ReadFully(fd_, &header_, sizeof(header_))) {
113         PLOG(ERROR) << "read header failed";
114         return false;
115     }
116 
117     if (header_.magic != kCowMagicNumber) {
118         LOG(ERROR) << "Header Magic corrupted. Magic: " << header_.magic
119                    << "Expected: " << kCowMagicNumber;
120         return false;
121     }
122     if (header_.footer_size != sizeof(CowFooter)) {
123         LOG(ERROR) << "Footer size unknown, read " << header_.footer_size << ", expected "
124                    << sizeof(CowFooter);
125         return false;
126     }
127     if (header_.op_size != sizeof(CowOperation)) {
128         LOG(ERROR) << "Operation size unknown, read " << header_.op_size << ", expected "
129                    << sizeof(CowOperation);
130         return false;
131     }
132     if (header_.cluster_ops == 1) {
133         LOG(ERROR) << "Clusters must contain at least two operations to function.";
134         return false;
135     }
136     if (header_.op_size != sizeof(CowOperation)) {
137         LOG(ERROR) << "Operation size unknown, read " << header_.op_size << ", expected "
138                    << sizeof(CowOperation);
139         return false;
140     }
141     if (header_.cluster_ops == 1) {
142         LOG(ERROR) << "Clusters must contain at least two operations to function.";
143         return false;
144     }
145 
146     if ((header_.major_version > kCowVersionMajor) || (header_.minor_version != kCowVersionMinor)) {
147         LOG(ERROR) << "Header version mismatch";
148         LOG(ERROR) << "Major version: " << header_.major_version
149                    << "Expected: " << kCowVersionMajor;
150         LOG(ERROR) << "Minor version: " << header_.minor_version
151                    << "Expected: " << kCowVersionMinor;
152         return false;
153     }
154 
155     if (!ParseOps(label)) {
156         return false;
157     }
158     // If we're resuming a write, we're not ready to merge
159     if (label.has_value()) return true;
160     return PrepMergeOps();
161 }
162 
ParseOps(std::optional<uint64_t> label)163 bool CowReader::ParseOps(std::optional<uint64_t> label) {
164     uint64_t pos;
165     auto data_loc = std::make_shared<std::unordered_map<uint64_t, uint64_t>>();
166 
167     // Skip the scratch space
168     if (header_.major_version >= 2 && (header_.buffer_size > 0)) {
169         LOG(DEBUG) << " Scratch space found of size: " << header_.buffer_size;
170         size_t init_offset = header_.header_size + header_.buffer_size;
171         pos = lseek(fd_.get(), init_offset, SEEK_SET);
172         if (pos != init_offset) {
173             PLOG(ERROR) << "lseek ops failed";
174             return false;
175         }
176     } else {
177         pos = lseek(fd_.get(), header_.header_size, SEEK_SET);
178         if (pos != header_.header_size) {
179             PLOG(ERROR) << "lseek ops failed";
180             return false;
181         }
182         // Reading a v1 version of COW which doesn't have buffer_size.
183         header_.buffer_size = 0;
184     }
185     uint64_t data_pos = 0;
186 
187     if (header_.cluster_ops) {
188         data_pos = pos + header_.cluster_ops * sizeof(CowOperation);
189     } else {
190         data_pos = pos + sizeof(CowOperation);
191     }
192 
193     auto ops_buffer = std::make_shared<std::vector<CowOperation>>();
194     uint64_t current_op_num = 0;
195     uint64_t cluster_ops = header_.cluster_ops ?: 1;
196     bool done = false;
197 
198     // Alternating op clusters and data
199     while (!done) {
200         uint64_t to_add = std::min(cluster_ops, (fd_size_ - pos) / sizeof(CowOperation));
201         if (to_add == 0) break;
202         ops_buffer->resize(current_op_num + to_add);
203         if (!android::base::ReadFully(fd_, &ops_buffer->data()[current_op_num],
204                                       to_add * sizeof(CowOperation))) {
205             PLOG(ERROR) << "read op failed";
206             return false;
207         }
208         // Parse current cluster to find start of next cluster
209         while (current_op_num < ops_buffer->size()) {
210             auto& current_op = ops_buffer->data()[current_op_num];
211             current_op_num++;
212             if (current_op.type == kCowXorOp) {
213                 data_loc->insert({current_op.new_block, data_pos});
214             }
215             pos += sizeof(CowOperation) + GetNextOpOffset(current_op, header_.cluster_ops);
216             data_pos += current_op.data_length + GetNextDataOffset(current_op, header_.cluster_ops);
217 
218             if (current_op.type == kCowClusterOp) {
219                 break;
220             } else if (current_op.type == kCowLabelOp) {
221                 last_label_ = {current_op.source};
222 
223                 // If we reach the requested label, stop reading.
224                 if (label && label.value() == current_op.source) {
225                     done = true;
226                     break;
227                 }
228             } else if (current_op.type == kCowFooterOp) {
229                 footer_.emplace();
230                 CowFooter* footer = &footer_.value();
231                 memcpy(&footer_->op, &current_op, sizeof(footer->op));
232                 off_t offs = lseek(fd_.get(), pos, SEEK_SET);
233                 if (offs < 0 || pos != static_cast<uint64_t>(offs)) {
234                     PLOG(ERROR) << "lseek next op failed " << offs;
235                     return false;
236                 }
237                 if (!android::base::ReadFully(fd_, &footer->data, sizeof(footer->data))) {
238                     LOG(ERROR) << "Could not read COW footer";
239                     return false;
240                 }
241 
242                 // Drop the footer from the op stream.
243                 current_op_num--;
244                 done = true;
245                 break;
246             } else if (current_op.type == kCowSequenceOp) {
247                 has_seq_ops_ = true;
248             }
249         }
250 
251         // Position for next cluster read
252         off_t offs = lseek(fd_.get(), pos, SEEK_SET);
253         if (offs < 0 || pos != static_cast<uint64_t>(offs)) {
254             PLOG(ERROR) << "lseek next op failed " << offs;
255             return false;
256         }
257         ops_buffer->resize(current_op_num);
258     }
259 
260     LOG(DEBUG) << "COW file read complete. Total ops: " << ops_buffer->size();
261     // To successfully parse a COW file, we need either:
262     //  (1) a label to read up to, and for that label to be found, or
263     //  (2) a valid footer.
264     if (label) {
265         if (!last_label_) {
266             LOG(ERROR) << "Did not find label " << label.value()
267                        << " while reading COW (no labels found)";
268             return false;
269         }
270         if (last_label_.value() != label.value()) {
271             LOG(ERROR) << "Did not find label " << label.value()
272                        << ", last label=" << last_label_.value();
273             return false;
274         }
275     } else if (!footer_) {
276         LOG(ERROR) << "No COW footer found";
277         return false;
278     }
279 
280     uint8_t csum[32];
281     memset(csum, 0, sizeof(uint8_t) * 32);
282 
283     if (footer_) {
284         if (ops_buffer->size() != footer_->op.num_ops) {
285             LOG(ERROR) << "num ops does not match, expected " << footer_->op.num_ops << ", found "
286                        << ops_buffer->size();
287             return false;
288         }
289         if (ops_buffer->size() * sizeof(CowOperation) != footer_->op.ops_size) {
290             LOG(ERROR) << "ops size does not match ";
291             return false;
292         }
293         SHA256(&footer_->op, sizeof(footer_->op), footer_->data.footer_checksum);
294         if (memcmp(csum, footer_->data.ops_checksum, sizeof(csum)) != 0) {
295             LOG(ERROR) << "ops checksum does not match";
296             return false;
297         }
298         SHA256(ops_buffer->data(), footer_->op.ops_size, csum);
299         if (memcmp(csum, footer_->data.ops_checksum, sizeof(csum)) != 0) {
300             LOG(ERROR) << "ops checksum does not match";
301             return false;
302         }
303     }
304 
305     ops_ = ops_buffer;
306     ops_->shrink_to_fit();
307     data_loc_ = data_loc;
308 
309     return true;
310 }
311 
312 //
313 // This sets up the data needed for MergeOpIter. MergeOpIter presents
314 // data in the order we intend to merge in.
315 //
316 // We merge all order sensitive ops up front, and sort the rest to allow for
317 // batch merging. Order sensitive ops can either be presented in their proper
318 // order in the cow, or be ordered by sequence ops (kCowSequenceOp), in which
319 // case we want to merge those ops first, followed by any ops not specified by
320 // new_block value by the sequence op, in sorted order.
321 // We will re-arrange the vector in such a way that
322 // kernel can batch merge. Ex:
323 //
324 // Existing COW format; All the copy operations
325 // are at the beginning.
326 // =======================================
327 // Copy-op-1    - cow_op->new_block = 1
328 // Copy-op-2    - cow_op->new_block = 2
329 // Copy-op-3    - cow_op->new_block = 3
330 // Replace-op-4 - cow_op->new_block = 6
331 // Replace-op-5 - cow_op->new_block = 4
332 // Replace-op-6 - cow_op->new_block = 8
333 // Replace-op-7 - cow_op->new_block = 9
334 // Zero-op-8    - cow_op->new_block = 7
335 // Zero-op-9    - cow_op->new_block = 5
336 // =======================================
337 //
338 // First find the operation which isn't a copy-op
339 // and then sort all the operations in descending order
340 // with the key being cow_op->new_block (source block)
341 //
342 // The data-structure will look like:
343 //
344 // =======================================
345 // Copy-op-1    - cow_op->new_block = 1
346 // Copy-op-2    - cow_op->new_block = 2
347 // Copy-op-3    - cow_op->new_block = 3
348 // Replace-op-7 - cow_op->new_block = 9
349 // Replace-op-6 - cow_op->new_block = 8
350 // Zero-op-8    - cow_op->new_block = 7
351 // Replace-op-4 - cow_op->new_block = 6
352 // Zero-op-9    - cow_op->new_block = 5
353 // Replace-op-5 - cow_op->new_block = 4
354 // =======================================
355 //
356 // Daemon will read the above data-structure in reverse-order
357 // when reading metadata. Thus, kernel will get the metadata
358 // in the following order:
359 //
360 // ========================================
361 // Replace-op-5 - cow_op->new_block = 4
362 // Zero-op-9    - cow_op->new_block = 5
363 // Replace-op-4 - cow_op->new_block = 6
364 // Zero-op-8    - cow_op->new_block = 7
365 // Replace-op-6 - cow_op->new_block = 8
366 // Replace-op-7 - cow_op->new_block = 9
367 // Copy-op-3    - cow_op->new_block = 3
368 // Copy-op-2    - cow_op->new_block = 2
369 // Copy-op-1    - cow_op->new_block = 1
370 // ===========================================
371 //
372 // When merging begins, kernel will start from the last
373 // metadata which was read: In the above format, Copy-op-1
374 // will be the first merge operation.
375 //
376 // Now, batching of the merge operations happens only when
377 // 1: origin block numbers in the base device are contiguous
378 // (cow_op->new_block) and,
379 // 2: cow block numbers which are assigned by daemon in ReadMetadata()
380 // are contiguous. These are monotonically increasing numbers.
381 //
382 // When both (1) and (2) are true, kernel will batch merge the operations.
383 // In the above case, we have to ensure that the copy operations
384 // are merged first before replace operations are done. Hence,
385 // we will not change the order of copy operations. Since,
386 // cow_op->new_block numbers are contiguous, we will ensure that the
387 // cow block numbers assigned in ReadMetadata() for these respective copy
388 // operations are not contiguous forcing kernel to issue merge for each
389 // copy operations without batch merging.
390 //
391 // For all the other operations viz. Replace and Zero op, the cow block
392 // numbers assigned by daemon will be contiguous allowing kernel to batch
393 // merge.
394 //
395 // The final format after assiging COW block numbers by the daemon will
396 // look something like:
397 //
398 // =========================================================
399 // Replace-op-5 - cow_op->new_block = 4  cow-block-num = 2
400 // Zero-op-9    - cow_op->new_block = 5  cow-block-num = 3
401 // Replace-op-4 - cow_op->new_block = 6  cow-block-num = 4
402 // Zero-op-8    - cow_op->new_block = 7  cow-block-num = 5
403 // Replace-op-6 - cow_op->new_block = 8  cow-block-num = 6
404 // Replace-op-7 - cow_op->new_block = 9  cow-block-num = 7
405 // Copy-op-3    - cow_op->new_block = 3  cow-block-num = 9
406 // Copy-op-2    - cow_op->new_block = 2  cow-block-num = 11
407 // Copy-op-1    - cow_op->new_block = 1  cow-block-num = 13
408 // ==========================================================
409 //
410 // Merge sequence will look like:
411 //
412 // Merge-1 - Batch-merge { Copy-op-1, Copy-op-2, Copy-op-3 }
413 // Merge-2 - Batch-merge {Replace-op-7, Replace-op-6, Zero-op-8,
414 //                        Replace-op-4, Zero-op-9, Replace-op-5 }
415 //==============================================================
PrepMergeOps()416 bool CowReader::PrepMergeOps() {
417     auto merge_op_blocks = std::make_unique<std::vector<uint32_t>>();
418     std::vector<int> other_ops;
419     auto seq_ops_set = std::unordered_set<uint32_t>();
420     auto block_map = std::make_unique<std::unordered_map<uint32_t, int>>();
421     size_t num_seqs = 0;
422     size_t read;
423 
424     for (size_t i = 0; i < ops_->size(); i++) {
425         auto& current_op = ops_->data()[i];
426 
427         if (current_op.type == kCowSequenceOp) {
428             size_t seq_len = current_op.data_length / sizeof(uint32_t);
429 
430             merge_op_blocks->resize(merge_op_blocks->size() + seq_len);
431             if (!GetRawBytes(current_op.source, &merge_op_blocks->data()[num_seqs],
432                              current_op.data_length, &read)) {
433                 PLOG(ERROR) << "Failed to read sequence op!";
434                 return false;
435             }
436             for (size_t j = num_seqs; j < num_seqs + seq_len; j++) {
437                 seq_ops_set.insert(merge_op_blocks->data()[j]);
438             }
439             num_seqs += seq_len;
440         }
441 
442         if (IsMetadataOp(current_op)) {
443             continue;
444         }
445 
446         if (!has_seq_ops_ && IsOrderedOp(current_op)) {
447             merge_op_blocks->emplace_back(current_op.new_block);
448         } else if (seq_ops_set.count(current_op.new_block) == 0) {
449             other_ops.push_back(current_op.new_block);
450         }
451         block_map->insert({current_op.new_block, i});
452     }
453     for (auto block : *merge_op_blocks) {
454         if (block_map->count(block) == 0) {
455             LOG(ERROR) << "Invalid Sequence Ops. Could not find Cow Op for new block " << block;
456             return false;
457         }
458     }
459 
460     if (merge_op_blocks->size() > header_.num_merge_ops) {
461         num_ordered_ops_to_merge_ = merge_op_blocks->size() - header_.num_merge_ops;
462     } else {
463         num_ordered_ops_to_merge_ = 0;
464     }
465 
466     // Sort the vector in increasing order if merging in user-space as
467     // we can batch merge them when iterating from forward.
468     //
469     // dm-snapshot-merge requires decreasing order as we iterate the blocks
470     // in reverse order.
471     if (reader_flag_ == ReaderFlags::USERSPACE_MERGE) {
472         std::sort(other_ops.begin(), other_ops.end());
473     } else {
474         std::sort(other_ops.begin(), other_ops.end(), std::greater<int>());
475     }
476 
477     merge_op_blocks->insert(merge_op_blocks->end(), other_ops.begin(), other_ops.end());
478 
479     for (auto block : *merge_op_blocks) {
480         block_pos_index_->push_back(block_map->at(block));
481     }
482 
483     num_total_data_ops_ = merge_op_blocks->size();
484     if (header_.num_merge_ops > 0) {
485         merge_op_start_ = header_.num_merge_ops;
486     }
487 
488     block_map->clear();
489     merge_op_blocks->clear();
490 
491     return true;
492 }
493 
VerifyMergeOps()494 bool CowReader::VerifyMergeOps() {
495     auto itr = GetMergeOpIter(true);
496     std::unordered_map<uint64_t, CowOperation> overwritten_blocks;
497     while (!itr->Done()) {
498         CowOperation op = itr->Get();
499         uint64_t block;
500         bool offset;
501         if (op.type == kCowCopyOp) {
502             block = op.source;
503             offset = false;
504         } else if (op.type == kCowXorOp) {
505             block = op.source / BLOCK_SZ;
506             offset = (op.source % BLOCK_SZ) != 0;
507         } else {
508             itr->Next();
509             continue;
510         }
511 
512         CowOperation* overwrite = nullptr;
513         if (overwritten_blocks.count(block)) {
514             overwrite = &overwritten_blocks[block];
515             LOG(ERROR) << "Invalid Sequence! Block needed for op:\n"
516                        << op << "\noverwritten by previously merged op:\n"
517                        << *overwrite;
518         }
519         if (offset && overwritten_blocks.count(block + 1)) {
520             overwrite = &overwritten_blocks[block + 1];
521             LOG(ERROR) << "Invalid Sequence! Block needed for op:\n"
522                        << op << "\noverwritten by previously merged op:\n"
523                        << *overwrite;
524         }
525         if (overwrite != nullptr) return false;
526         overwritten_blocks[op.new_block] = op;
527         itr->Next();
528     }
529     return true;
530 }
531 
GetHeader(CowHeader * header)532 bool CowReader::GetHeader(CowHeader* header) {
533     *header = header_;
534     return true;
535 }
536 
GetFooter(CowFooter * footer)537 bool CowReader::GetFooter(CowFooter* footer) {
538     if (!footer_) return false;
539     *footer = footer_.value();
540     return true;
541 }
542 
GetLastLabel(uint64_t * label)543 bool CowReader::GetLastLabel(uint64_t* label) {
544     if (!last_label_) return false;
545     *label = last_label_.value();
546     return true;
547 }
548 
549 class CowOpIter final : public ICowOpIter {
550   public:
551     CowOpIter(std::shared_ptr<std::vector<CowOperation>>& ops);
552 
553     bool Done() override;
554     const CowOperation& Get() override;
555     void Next() override;
556 
557     void Prev() override;
558     bool RDone() override;
559 
560   private:
561     std::shared_ptr<std::vector<CowOperation>> ops_;
562     std::vector<CowOperation>::iterator op_iter_;
563 };
564 
CowOpIter(std::shared_ptr<std::vector<CowOperation>> & ops)565 CowOpIter::CowOpIter(std::shared_ptr<std::vector<CowOperation>>& ops) {
566     ops_ = ops;
567     op_iter_ = ops_->begin();
568 }
569 
RDone()570 bool CowOpIter::RDone() {
571     return op_iter_ == ops_->begin();
572 }
573 
Prev()574 void CowOpIter::Prev() {
575     CHECK(!RDone());
576     op_iter_--;
577 }
578 
Done()579 bool CowOpIter::Done() {
580     return op_iter_ == ops_->end();
581 }
582 
Next()583 void CowOpIter::Next() {
584     CHECK(!Done());
585     op_iter_++;
586 }
587 
Get()588 const CowOperation& CowOpIter::Get() {
589     CHECK(!Done());
590     return (*op_iter_);
591 }
592 
593 class CowRevMergeOpIter final : public ICowOpIter {
594   public:
595     explicit CowRevMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
596                                std::shared_ptr<std::vector<int>> block_pos_index, uint64_t start);
597 
598     bool Done() override;
599     const CowOperation& Get() override;
600     void Next() override;
601 
602     void Prev() override;
603     bool RDone() override;
604 
605   private:
606     std::shared_ptr<std::vector<CowOperation>> ops_;
607     std::vector<int>::reverse_iterator block_riter_;
608     std::shared_ptr<std::vector<int>> cow_op_index_vec_;
609     uint64_t start_;
610 };
611 
612 class CowMergeOpIter final : public ICowOpIter {
613   public:
614     explicit CowMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
615                             std::shared_ptr<std::vector<int>> block_pos_index, uint64_t start);
616 
617     bool Done() override;
618     const CowOperation& Get() override;
619     void Next() override;
620 
621     void Prev() override;
622     bool RDone() override;
623 
624   private:
625     std::shared_ptr<std::vector<CowOperation>> ops_;
626     std::vector<int>::iterator block_iter_;
627     std::shared_ptr<std::vector<int>> cow_op_index_vec_;
628     uint64_t start_;
629 };
630 
CowMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,std::shared_ptr<std::vector<int>> block_pos_index,uint64_t start)631 CowMergeOpIter::CowMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
632                                std::shared_ptr<std::vector<int>> block_pos_index, uint64_t start) {
633     ops_ = ops;
634     start_ = start;
635     cow_op_index_vec_ = block_pos_index;
636     block_iter_ = cow_op_index_vec_->begin() + start;
637 }
638 
RDone()639 bool CowMergeOpIter::RDone() {
640     return block_iter_ == cow_op_index_vec_->begin();
641 }
642 
Prev()643 void CowMergeOpIter::Prev() {
644     CHECK(!RDone());
645     block_iter_--;
646 }
647 
Done()648 bool CowMergeOpIter::Done() {
649     return block_iter_ == cow_op_index_vec_->end();
650 }
651 
Next()652 void CowMergeOpIter::Next() {
653     CHECK(!Done());
654     block_iter_++;
655 }
656 
Get()657 const CowOperation& CowMergeOpIter::Get() {
658     CHECK(!Done());
659     return ops_->data()[*block_iter_];
660 }
661 
CowRevMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,std::shared_ptr<std::vector<int>> block_pos_index,uint64_t start)662 CowRevMergeOpIter::CowRevMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
663                                      std::shared_ptr<std::vector<int>> block_pos_index,
664                                      uint64_t start) {
665     ops_ = ops;
666     start_ = start;
667     cow_op_index_vec_ = block_pos_index;
668     block_riter_ = cow_op_index_vec_->rbegin();
669 }
670 
RDone()671 bool CowRevMergeOpIter::RDone() {
672     return block_riter_ == cow_op_index_vec_->rbegin();
673 }
674 
Prev()675 void CowRevMergeOpIter::Prev() {
676     CHECK(!RDone());
677     block_riter_--;
678 }
679 
Done()680 bool CowRevMergeOpIter::Done() {
681     return block_riter_ == cow_op_index_vec_->rend() - start_;
682 }
683 
Next()684 void CowRevMergeOpIter::Next() {
685     CHECK(!Done());
686     block_riter_++;
687 }
688 
Get()689 const CowOperation& CowRevMergeOpIter::Get() {
690     CHECK(!Done());
691     return ops_->data()[*block_riter_];
692 }
693 
GetOpIter()694 std::unique_ptr<ICowOpIter> CowReader::GetOpIter() {
695     return std::make_unique<CowOpIter>(ops_);
696 }
697 
GetRevMergeOpIter(bool ignore_progress)698 std::unique_ptr<ICowOpIter> CowReader::GetRevMergeOpIter(bool ignore_progress) {
699     return std::make_unique<CowRevMergeOpIter>(ops_, block_pos_index_,
700                                                ignore_progress ? 0 : merge_op_start_);
701 }
702 
GetMergeOpIter(bool ignore_progress)703 std::unique_ptr<ICowOpIter> CowReader::GetMergeOpIter(bool ignore_progress) {
704     return std::make_unique<CowMergeOpIter>(ops_, block_pos_index_,
705                                             ignore_progress ? 0 : merge_op_start_);
706 }
707 
GetRawBytes(uint64_t offset,void * buffer,size_t len,size_t * read)708 bool CowReader::GetRawBytes(uint64_t offset, void* buffer, size_t len, size_t* read) {
709     // Validate the offset, taking care to acknowledge possible overflow of offset+len.
710     if (offset < header_.header_size || offset >= fd_size_ - sizeof(CowFooter) || len >= fd_size_ ||
711         offset + len > fd_size_ - sizeof(CowFooter)) {
712         LOG(ERROR) << "invalid data offset: " << offset << ", " << len << " bytes";
713         return false;
714     }
715     if (lseek(fd_.get(), offset, SEEK_SET) < 0) {
716         PLOG(ERROR) << "lseek to read raw bytes failed";
717         return false;
718     }
719     ssize_t rv = TEMP_FAILURE_RETRY(::read(fd_.get(), buffer, len));
720     if (rv < 0) {
721         PLOG(ERROR) << "read failed";
722         return false;
723     }
724     *read = rv;
725     return true;
726 }
727 
728 class CowDataStream final : public IByteStream {
729   public:
CowDataStream(CowReader * reader,uint64_t offset,size_t data_length)730     CowDataStream(CowReader* reader, uint64_t offset, size_t data_length)
731         : reader_(reader), offset_(offset), data_length_(data_length) {
732         remaining_ = data_length_;
733     }
734 
Read(void * buffer,size_t length,size_t * read)735     bool Read(void* buffer, size_t length, size_t* read) override {
736         size_t to_read = std::min(length, remaining_);
737         if (!to_read) {
738             *read = 0;
739             return true;
740         }
741         if (!reader_->GetRawBytes(offset_, buffer, to_read, read)) {
742             return false;
743         }
744         offset_ += *read;
745         remaining_ -= *read;
746         return true;
747     }
748 
Size() const749     size_t Size() const override { return data_length_; }
750 
751   private:
752     CowReader* reader_;
753     uint64_t offset_;
754     size_t data_length_;
755     size_t remaining_;
756 };
757 
ReadData(const CowOperation & op,IByteSink * sink)758 bool CowReader::ReadData(const CowOperation& op, IByteSink* sink) {
759     std::unique_ptr<IDecompressor> decompressor;
760     switch (op.compression) {
761         case kCowCompressNone:
762             decompressor = IDecompressor::Uncompressed();
763             break;
764         case kCowCompressGz:
765             decompressor = IDecompressor::Gz();
766             break;
767         case kCowCompressBrotli:
768             decompressor = IDecompressor::Brotli();
769             break;
770         default:
771             LOG(ERROR) << "Unknown compression type: " << op.compression;
772             return false;
773     }
774 
775     uint64_t offset;
776     if (op.type == kCowXorOp) {
777         offset = data_loc_->at(op.new_block);
778     } else {
779         offset = op.source;
780     }
781     CowDataStream stream(this, offset, op.data_length);
782     decompressor->set_stream(&stream);
783     decompressor->set_sink(sink);
784     return decompressor->Decompress(header_.block_size);
785 }
786 
787 }  // namespace snapshot
788 }  // namespace android
789