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 23 #include <android-base/unique_fd.h> 24 #include <libsnapshot/cow_format.h> 25 26 namespace android { 27 namespace snapshot { 28 29 class ICowOpIter; 30 class ICowOpReverseIter; 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 72 // Return the last valid label 73 virtual bool GetLastLabel(uint64_t* label) = 0; 74 75 // Return an iterator for retrieving CowOperation entries. 76 virtual std::unique_ptr<ICowOpIter> GetOpIter() = 0; 77 78 // Return an reverse iterator for retrieving CowOperation entries. 79 virtual std::unique_ptr<ICowOpReverseIter> GetRevOpIter() = 0; 80 81 // Get decoded bytes from the data section, handling any decompression. 82 // All retrieved data is passed to the sink. 83 virtual bool ReadData(const CowOperation& op, IByteSink* sink) = 0; 84 }; 85 86 // Iterate over a sequence of COW operations. 87 class ICowOpIter { 88 public: ~ICowOpIter()89 virtual ~ICowOpIter() {} 90 91 // True if there are more items to read, false otherwise. 92 virtual bool Done() = 0; 93 94 // Read the current operation. 95 virtual const CowOperation& Get() = 0; 96 97 // Advance to the next item. 98 virtual void Next() = 0; 99 }; 100 101 // Reverse Iterate over a sequence of COW operations. 102 class ICowOpReverseIter { 103 public: ~ICowOpReverseIter()104 virtual ~ICowOpReverseIter() {} 105 106 // True if there are more items to read, false otherwise. 107 virtual bool Done() = 0; 108 109 // Read the current operation. 110 virtual const CowOperation& Get() = 0; 111 112 // Advance to the next item. 113 virtual void Next() = 0; 114 }; 115 116 class CowReader : public ICowReader { 117 public: 118 CowReader(); ~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 128 bool GetHeader(CowHeader* header) override; 129 bool GetFooter(CowFooter* footer) override; 130 131 bool GetLastLabel(uint64_t* label) override; 132 133 // Create a CowOpIter object which contains footer_.num_ops 134 // CowOperation objects. Get() returns a unique CowOperation object 135 // whose lifetime depends on the CowOpIter object; the return 136 // value of these will never be null. 137 std::unique_ptr<ICowOpIter> GetOpIter() override; 138 std::unique_ptr<ICowOpReverseIter> GetRevOpIter() override; 139 140 bool ReadData(const CowOperation& op, IByteSink* sink) override; 141 142 bool GetRawBytes(uint64_t offset, void* buffer, size_t len, size_t* read); 143 144 void InitializeMerge(); 145 146 // Number of copy, replace, and zero ops. Set if InitializeMerge is called. set_total_data_ops(uint64_t size)147 void set_total_data_ops(uint64_t size) { total_data_ops_ = size; } total_data_ops()148 uint64_t total_data_ops() { return total_data_ops_; } 149 // Number of copy ops. Set if InitializeMerge is called. set_copy_ops(uint64_t size)150 void set_copy_ops(uint64_t size) { copy_ops_ = size; } total_copy_ops()151 uint64_t total_copy_ops() { return copy_ops_; } 152 CloseCowFd()153 void CloseCowFd() { owned_fd_ = {}; } 154 155 private: 156 bool ParseOps(std::optional<uint64_t> label); 157 uint64_t FindNumCopyops(); 158 159 android::base::unique_fd owned_fd_; 160 android::base::borrowed_fd fd_; 161 CowHeader header_; 162 std::optional<CowFooter> footer_; 163 uint64_t fd_size_; 164 std::optional<uint64_t> last_label_; 165 std::shared_ptr<std::vector<CowOperation>> ops_; 166 uint64_t total_data_ops_; 167 uint64_t copy_ops_; 168 }; 169 170 } // namespace snapshot 171 } // namespace android 172