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