1 // Copyright (C) 2019 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 
17 #include <stdint.h>
18 
19 #include <memory>
20 #include <optional>
21 #include <unordered_map>
22 #include <vector>
23 
24 #include <android-base/unique_fd.h>
25 #include <libsnapshot/cow_format.h>
26 
27 namespace chromeos_update_engine {
28 class FileDescriptor;
29 }  // namespace chromeos_update_engine
30 
31 namespace android {
32 namespace snapshot {
33 
34 class ICowOpIter;
35 
36 // Interface for reading from a snapuserd COW.
37 class ICowReader {
38   public:
39     using FileDescriptor = chromeos_update_engine::FileDescriptor;
40 
~ICowReader()41     virtual ~ICowReader() {}
42 
43     // Return the file header.
44     virtual CowHeader& GetHeader() = 0;
45 
46     // Return the file footer.
47     virtual bool GetFooter(CowFooter* footer) = 0;
48     virtual bool VerifyMergeOps() = 0;
49 
50     // Return the last valid label
51     virtual bool GetLastLabel(uint64_t* label) = 0;
52 
53     // Return an iterator for retrieving CowOperation entries.
54     virtual std::unique_ptr<ICowOpIter> GetOpIter(bool merge_progress) = 0;
55 
56     // Return an iterator for retrieving CowOperation entries in reverse merge order
57     virtual std::unique_ptr<ICowOpIter> GetRevMergeOpIter(bool ignore_progress) = 0;
58 
59     // Return an iterator for retrieving CowOperation entries in merge order
60     virtual std::unique_ptr<ICowOpIter> GetMergeOpIter(bool ignore_progress) = 0;
61 
62     // Get decoded bytes from the data section, handling any decompression.
63     //
64     // If ignore_bytes is non-zero, it specifies the initial number of bytes
65     // to skip writing to |buffer|.
66     //
67     // Returns the number of bytes written to |buffer|, or -1 on failure.
68     // errno is NOT set.
69     //
70     // Partial reads are not possible unless |buffer_size| is less than the
71     // operation block size.
72     //
73     // The operation pointer must derive from ICowOpIter::Get().
74     virtual ssize_t ReadData(const CowOperation* op, void* buffer, size_t buffer_size,
75                              size_t ignore_bytes = 0) = 0;
76 
77     // Get the absolute source offset, in bytes, of a CowOperation. Returns
78     // false if the operation does not read from source partitions.
79     virtual bool GetSourceOffset(const CowOperation* op, uint64_t* source_offset) = 0;
80 };
81 
GetBlockFromOffset(const CowHeader & header,uint64_t offset)82 static constexpr uint64_t GetBlockFromOffset(const CowHeader& header, uint64_t offset) {
83     return offset / header.block_size;
84 }
85 
GetBlockRelativeOffset(const CowHeader & header,uint64_t offset)86 static constexpr uint64_t GetBlockRelativeOffset(const CowHeader& header, uint64_t offset) {
87     return offset % header.block_size;
88 }
89 
90 // Iterate over a sequence of COW operations. The iterator is bidirectional.
91 class ICowOpIter {
92   public:
~ICowOpIter()93     virtual ~ICowOpIter() {}
94 
95     // Returns true if the iterator is at the end of the operation list.
96     // If true, Get() and Next() must not be called.
97     virtual bool AtEnd() = 0;
98 
99     // Read the current operation.
100     virtual const CowOperation* Get() = 0;
101 
102     // Advance to the next item.
103     virtual void Next() = 0;
104 
105     // Returns true if the iterator is at the beginning of the operation list.
106     // If true, Prev() must not be called; Get() however will be valid if
107     // AtEnd() is not true.
108     virtual bool AtBegin() = 0;
109 
110     // Advance to the previous item.
111     virtual void Prev() = 0;
112 };
113 
114 class CowReader final : public ICowReader {
115   public:
116     enum class ReaderFlags {
117         DEFAULT = 0,
118         USERSPACE_MERGE = 1,
119     };
120 
121     CowReader(ReaderFlags reader_flag = ReaderFlags::DEFAULT, bool is_merge = false);
~CowReader()122     ~CowReader() { owned_fd_ = {}; }
123 
124     // Parse the COW, optionally, up to the given label. If no label is
125     // specified, the COW must have an intact footer.
126     bool Parse(android::base::unique_fd&& fd, std::optional<uint64_t> label = {});
127     bool Parse(android::base::borrowed_fd fd, std::optional<uint64_t> label = {});
128 
129     bool InitForMerge(android::base::unique_fd&& fd);
130 
131     bool VerifyMergeOps() override;
132     bool GetFooter(CowFooter* footer) override;
133     bool GetLastLabel(uint64_t* label) override;
134     bool GetSourceOffset(const CowOperation* op, uint64_t* source_offset) override;
135 
136     // Create a CowOpIter object which contains footer_.num_ops
137     // CowOperation objects. Get() returns a unique CowOperation object
138     // whose lifetime depends on the CowOpIter object; the return
139     // value of these will never be null.
140     std::unique_ptr<ICowOpIter> GetOpIter(bool merge_progress = false) override;
141     std::unique_ptr<ICowOpIter> GetRevMergeOpIter(bool ignore_progress = false) override;
142     std::unique_ptr<ICowOpIter> GetMergeOpIter(bool ignore_progress = false) override;
143 
144     ssize_t ReadData(const CowOperation* op, void* buffer, size_t buffer_size,
145                      size_t ignore_bytes = 0) override;
146 
GetHeader()147     CowHeader& GetHeader() override { return header_; }
header_v3()148     const CowHeaderV3& header_v3() const { return header_; }
149 
150     bool GetRawBytes(const CowOperation* op, void* buffer, size_t len, size_t* read);
151     bool GetRawBytes(uint64_t offset, void* buffer, size_t len, size_t* read);
152 
153     // Returns the total number of data ops that should be merged. This is the
154     // count of the merge sequence before removing already-merged operations.
155     // It may be different than the actual data op count, for example, if there
156     // are duplicate ops in the stream.
get_num_total_data_ops()157     uint64_t get_num_total_data_ops() { return num_total_data_ops_; }
158 
get_num_ordered_ops_to_merge()159     uint64_t get_num_ordered_ops_to_merge() { return num_ordered_ops_to_merge_; }
160 
CloseCowFd()161     void CloseCowFd() { owned_fd_ = {}; }
162 
163     // Creates a clone of the current CowReader without the file handlers
164     std::unique_ptr<CowReader> CloneCowReader();
165 
166     // Get the max compression size
167     uint32_t GetMaxCompressionSize();
168 
UpdateMergeOpsCompleted(int num_merge_ops)169     void UpdateMergeOpsCompleted(int num_merge_ops) { header_.num_merge_ops += num_merge_ops; }
170 
171   private:
172     bool ParseV2(android::base::borrowed_fd fd, std::optional<uint64_t> label);
173     bool PrepMergeOps();
174     // sequence data is stored as an operation with actual data residing in the data offset.
175     bool GetSequenceDataV2(std::vector<uint32_t>* merge_op_blocks, std::vector<int>* other_ops,
176                            std::unordered_map<uint32_t, int>* block_map);
177     // v3 of the cow writes sequence data within its own separate sequence buffer.
178     bool GetSequenceData(std::vector<uint32_t>* merge_op_blocks, std::vector<int>* other_ops,
179                          std::unordered_map<uint32_t, int>* block_map);
180     uint64_t FindNumCopyops();
181     uint8_t GetCompressionType();
182 
183     android::base::unique_fd owned_fd_;
184     android::base::borrowed_fd fd_;
185     CowHeaderV3 header_;
186     std::optional<CowFooter> footer_;
187     uint64_t fd_size_;
188     std::optional<uint64_t> last_label_;
189     std::shared_ptr<std::vector<CowOperation>> ops_;
190     uint64_t merge_op_start_{};
191     std::shared_ptr<std::vector<int>> block_pos_index_;
192     uint64_t num_total_data_ops_{};
193     uint64_t num_ordered_ops_to_merge_{};
194     bool has_seq_ops_{};
195     std::shared_ptr<std::unordered_map<uint64_t, uint64_t>> xor_data_loc_;
196     ReaderFlags reader_flag_;
197     bool is_merge_{};
198 };
199 
200 // Though this function takes in a CowHeaderV3, the struct could be populated as a v1/v2 CowHeader.
201 // The extra fields will just be filled as 0. V3 header is strictly a superset of v1/v2 header and
202 // contains all of the latter's field
203 bool ReadCowHeader(android::base::borrowed_fd fd, CowHeaderV3* header);
204 }  // namespace snapshot
205 }  // namespace android
206