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 <functional> 20 #include <memory> 21 #include <optional> 22 #include <unordered_map> 23 24 #include <android-base/unique_fd.h> 25 #include <libsnapshot/cow_format.h> 26 27 namespace android { 28 namespace snapshot { 29 30 class ICowOpIter; 31 32 // A ByteSink object handles requests for a buffer of a specific size. It 33 // always owns the underlying buffer. It's designed to minimize potential 34 // copying as we parse or decompress the COW. 35 class IByteSink { 36 public: ~IByteSink()37 virtual ~IByteSink() {} 38 39 // Called when the reader has data. The size of the request is given. The 40 // sink must return a valid pointer (or null on failure), and return the 41 // maximum number of bytes that can be written to the returned buffer. 42 // 43 // The returned buffer is owned by IByteSink, but must remain valid until 44 // the read operation has completed (or the entire buffer has been 45 // covered by calls to ReturnData). 46 // 47 // After calling GetBuffer(), all previous buffers returned are no longer 48 // valid. 49 // 50 // GetBuffer() is intended to be sequential. A returned size of N indicates 51 // that the output stream will advance by N bytes, and the ReturnData call 52 // indicates that those bytes have been fulfilled. Therefore, it is 53 // possible to have ReturnBuffer do nothing, if the implementation doesn't 54 // care about incremental writes. 55 virtual void* GetBuffer(size_t requested, size_t* actual) = 0; 56 57 // Called when a section returned by |GetBuffer| has been filled with data. 58 virtual bool ReturnData(void* buffer, size_t length) = 0; 59 }; 60 61 // Interface for reading from a snapuserd COW. 62 class ICowReader { 63 public: ~ICowReader()64 virtual ~ICowReader() {} 65 66 // Return the file header. 67 virtual bool GetHeader(CowHeader* header) = 0; 68 69 // Return the file footer. 70 virtual bool GetFooter(CowFooter* footer) = 0; 71 virtual bool VerifyMergeOps() = 0; 72 73 // Return the last valid label 74 virtual bool GetLastLabel(uint64_t* label) = 0; 75 76 // Return an iterator for retrieving CowOperation entries. 77 virtual std::unique_ptr<ICowOpIter> GetOpIter(bool merge_progress) = 0; 78 79 // Return an iterator for retrieving CowOperation entries in reverse merge order 80 virtual std::unique_ptr<ICowOpIter> GetRevMergeOpIter(bool ignore_progress) = 0; 81 82 // Return an iterator for retrieving CowOperation entries in merge order 83 virtual std::unique_ptr<ICowOpIter> GetMergeOpIter(bool ignore_progress) = 0; 84 85 // Get decoded bytes from the data section, handling any decompression. 86 // All retrieved data is passed to the sink. 87 virtual bool ReadData(const CowOperation& op, IByteSink* sink) = 0; 88 }; 89 90 // Iterate over a sequence of COW operations. 91 class ICowOpIter { 92 public: ~ICowOpIter()93 virtual ~ICowOpIter() {} 94 95 // True if there are no more items to read forward, false otherwise. 96 virtual bool Done() = 0; 97 98 // Read the current operation. 99 virtual const CowOperation& Get() = 0; 100 101 // Advance to the next item. 102 virtual void Next() = 0; 103 104 // Advance to the previous item. 105 virtual void Prev() = 0; 106 107 // True if there are no more items to read backwards, false otherwise 108 virtual bool RDone() = 0; 109 }; 110 111 class CowReader final : public ICowReader { 112 public: 113 enum class ReaderFlags { 114 DEFAULT = 0, 115 USERSPACE_MERGE = 1, 116 }; 117 118 CowReader(ReaderFlags reader_flag = ReaderFlags::DEFAULT, bool is_merge = false); ~CowReader()119 ~CowReader() { owned_fd_ = {}; } 120 121 // Parse the COW, optionally, up to the given label. If no label is 122 // specified, the COW must have an intact footer. 123 bool Parse(android::base::unique_fd&& fd, std::optional<uint64_t> label = {}); 124 bool Parse(android::base::borrowed_fd fd, std::optional<uint64_t> label = {}); 125 126 bool InitForMerge(android::base::unique_fd&& fd); 127 bool VerifyMergeOps() override; 128 129 bool GetHeader(CowHeader* header) override; 130 bool GetFooter(CowFooter* footer) override; 131 132 bool GetLastLabel(uint64_t* label) override; 133 134 // Create a CowOpIter object which contains footer_.num_ops 135 // CowOperation objects. Get() returns a unique CowOperation object 136 // whose lifetime depends on the CowOpIter object; the return 137 // value of these will never be null. 138 std::unique_ptr<ICowOpIter> GetOpIter(bool merge_progress = false) override; 139 std::unique_ptr<ICowOpIter> GetRevMergeOpIter(bool ignore_progress = false) override; 140 std::unique_ptr<ICowOpIter> GetMergeOpIter(bool ignore_progress = false) override; 141 142 bool ReadData(const CowOperation& op, IByteSink* sink) override; 143 144 bool GetRawBytes(uint64_t offset, void* buffer, size_t len, size_t* read); 145 146 // Returns the total number of data ops that should be merged. This is the 147 // count of the merge sequence before removing already-merged operations. 148 // It may be different than the actual data op count, for example, if there 149 // are duplicate ops in the stream. get_num_total_data_ops()150 uint64_t get_num_total_data_ops() { return num_total_data_ops_; } 151 get_num_ordered_ops_to_merge()152 uint64_t get_num_ordered_ops_to_merge() { return num_ordered_ops_to_merge_; } 153 CloseCowFd()154 void CloseCowFd() { owned_fd_ = {}; } 155 156 // Creates a clone of the current CowReader without the file handlers 157 std::unique_ptr<CowReader> CloneCowReader(); 158 UpdateMergeOpsCompleted(int num_merge_ops)159 void UpdateMergeOpsCompleted(int num_merge_ops) { header_.num_merge_ops += num_merge_ops; } 160 161 private: 162 bool ParseOps(std::optional<uint64_t> label); 163 bool PrepMergeOps(); 164 uint64_t FindNumCopyops(); 165 166 android::base::unique_fd owned_fd_; 167 android::base::borrowed_fd fd_; 168 CowHeader header_; 169 std::optional<CowFooter> footer_; 170 uint64_t fd_size_; 171 std::optional<uint64_t> last_label_; 172 std::shared_ptr<std::vector<CowOperation>> ops_; 173 uint64_t merge_op_start_{}; 174 std::shared_ptr<std::vector<int>> block_pos_index_; 175 uint64_t num_total_data_ops_{}; 176 uint64_t num_ordered_ops_to_merge_{}; 177 bool has_seq_ops_{}; 178 std::shared_ptr<std::unordered_map<uint64_t, uint64_t>> data_loc_; 179 ReaderFlags reader_flag_; 180 bool is_merge_{}; 181 }; 182 183 } // namespace snapshot 184 } // namespace android 185