• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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