• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 #pragma once
17 
18 #include <unistd.h>
19 
20 #include <array>
21 #include <chrono>
22 #include <functional>
23 #include <optional>
24 #include <string>
25 #include <string_view>
26 #include <utility>
27 #include <vector>
28 
29 #include "incfs_ndk.h"
30 
31 namespace android::incfs {
32 
33 using ByteBuffer = std::vector<char>;
34 
35 enum MountFlags {
36     createOnly = INCFS_MOUNT_CREATE_ONLY,
37     truncate = INCFS_MOUNT_TRUNCATE,
38 };
39 
40 enum Features {
41     none = INCFS_FEATURE_NONE,
42     core = INCFS_FEATURE_CORE,
43     v2 = INCFS_FEATURE_V2,
44     mappingFilesProgressFixed = INCFS_FEATURE_MAPPING_FILES_PROGRESS_FIXED,
45 };
46 
47 enum class HashAlgorithm {
48     none = INCFS_HASH_NONE,
49     sha256 = INCFS_HASH_SHA256,
50 };
51 
52 enum class CompressionKind {
53     none = INCFS_COMPRESSION_KIND_NONE,
54     lz4 = INCFS_COMPRESSION_KIND_LZ4,
55     zstd = INCFS_COMPRESSION_KIND_ZSTD,
56 };
57 
58 enum class BlockKind {
59     data = INCFS_BLOCK_KIND_DATA,
60     hash = INCFS_BLOCK_KIND_HASH,
61 };
62 
63 class UniqueFd {
64 public:
UniqueFd(int fd)65     explicit UniqueFd(int fd) : fd_(fd) {}
UniqueFd()66     UniqueFd() : UniqueFd(-1) {}
~UniqueFd()67     ~UniqueFd() { close(); }
UniqueFd(UniqueFd && other)68     UniqueFd(UniqueFd&& other) noexcept : fd_(other.release()) {}
69     UniqueFd& operator=(UniqueFd&& other) noexcept {
70         close();
71         fd_ = other.release();
72         return *this;
73     }
74 
close()75     void close() {
76         if (ok()) {
77             ::close(fd_);
78             fd_ = -1;
79         }
80     }
get()81     int get() const { return fd_; }
ok()82     [[nodiscard]] bool ok() const { return fd_ >= 0; }
release()83     [[nodiscard]] int release() { return std::exchange(fd_, -1); }
84 
85 private:
86     int fd_;
87 };
88 
89 class UniqueControl {
90 public:
mControl(control)91     UniqueControl(IncFsControl* control = nullptr) : mControl(control) {}
~UniqueControl()92     ~UniqueControl() { close(); }
UniqueControl(UniqueControl && other)93     UniqueControl(UniqueControl&& other) noexcept
94           : mControl(std::exchange(other.mControl, nullptr)) {}
95     UniqueControl& operator=(UniqueControl&& other) noexcept {
96         close();
97         mControl = std::exchange(other.mControl, nullptr);
98         return *this;
99     }
100 
101     IncFsFd cmd() const;
102     IncFsFd pendingReads() const;
103     IncFsFd logs() const;
104     IncFsFd blocksWritten() const;
105 
106     void close();
107 
108     operator IncFsControl*() const { return mControl; }
109 
110     using Fds = std::array<UniqueFd, IncFsFdType::FDS_COUNT>;
111     [[nodiscard]] Fds releaseFds();
112 
113 private:
114     IncFsControl* mControl;
115 };
116 
117 // A mini version of std::span
118 template <class T>
119 class Span {
120 public:
121     using iterator = T*;
122     using const_iterator = const T*;
123 
Span(T * array,size_t length)124     constexpr Span(T* array, size_t length) : ptr_(array), len_(length) {}
125     template <typename V>
Span(const std::vector<V> & x)126     constexpr Span(const std::vector<V>& x) : Span(x.data(), x.size()) {}
127     template <typename V, size_t Size>
Span(V (& x)[Size])128     constexpr Span(V (&x)[Size]) : Span(x, Size) {}
129 
data()130     constexpr T* data() const { return ptr_; }
size()131     constexpr size_t size() const { return len_; }
132     constexpr T& operator[](size_t i) const { return *(data() + i); }
begin()133     constexpr iterator begin() const { return data(); }
cbegin()134     constexpr const_iterator cbegin() const { return begin(); }
end()135     constexpr iterator end() const { return data() + size(); }
cend()136     constexpr const_iterator cend() const { return end(); }
137 
138 private:
139     T* ptr_;
140     size_t len_;
141 };
142 
143 struct BlockRange final : public IncFsBlockRange {
sizefinal144     constexpr size_t size() const { return end - begin; }
emptyfinal145     constexpr bool empty() const { return end == begin; }
146 };
147 
148 class FilledRanges final {
149 public:
150     using RangeBuffer = std::vector<BlockRange>;
151 
152     FilledRanges() = default;
FilledRanges(RangeBuffer && buffer,IncFsFilledRanges ranges)153     FilledRanges(RangeBuffer&& buffer, IncFsFilledRanges ranges)
154           : buffer_(std::move(buffer)), rawFilledRanges_(ranges) {}
155 
dataRanges()156     constexpr Span<BlockRange> dataRanges() const {
157         return {(BlockRange*)rawFilledRanges_.dataRanges, (size_t)rawFilledRanges_.dataRangesCount};
158     }
hashRanges()159     constexpr Span<BlockRange> hashRanges() const {
160         return {(BlockRange*)rawFilledRanges_.hashRanges, (size_t)rawFilledRanges_.hashRangesCount};
161     }
162 
totalSize()163     constexpr size_t totalSize() const { return dataRanges().size() + hashRanges().size(); }
164 
extractInternalBufferAndClear()165     RangeBuffer extractInternalBufferAndClear() {
166         rawFilledRanges_ = {};
167         return std::move(buffer_);
168     }
169 
internalBuffer()170     constexpr const RangeBuffer& internalBuffer() const { return buffer_; }
internalRawRanges()171     constexpr IncFsFilledRanges internalRawRanges() const { return rawFilledRanges_; }
172 
173 private:
174     RangeBuffer buffer_;
175     IncFsFilledRanges rawFilledRanges_;
176 };
177 
178 using Control = UniqueControl;
179 
180 using FileId = IncFsFileId;
181 using Size = IncFsSize;
182 using BlockIndex = IncFsBlockIndex;
183 using ErrorCode = IncFsErrorCode;
184 using Fd = IncFsFd;
185 using Uid = IncFsUid;
186 using ReadInfo = IncFsReadInfo;
187 using ReadInfoWithUid = IncFsReadInfoWithUid;
188 using RawMetadata = ByteBuffer;
189 using RawSignature = ByteBuffer;
190 using MountOptions = IncFsMountOptions;
191 using DataBlock = IncFsDataBlock;
192 using NewFileParams = IncFsNewFileParams;
193 using NewMappedFileParams = IncFsNewMappedFileParams;
194 using BlockCounts = IncFsBlockCounts;
195 using UidReadTimeouts = IncFsUidReadTimeouts;
196 using Metrics = IncFsMetrics;
197 using LastReadError = IncFsLastReadError;
198 
199 constexpr auto kDefaultReadTimeout = std::chrono::milliseconds(INCFS_DEFAULT_READ_TIMEOUT_MS);
200 constexpr int kBlockSize = INCFS_DATA_FILE_BLOCK_SIZE;
201 const auto kInvalidFileId = kIncFsInvalidFileId;
202 const auto kNoUid = kIncFsNoUid;
203 
204 bool enabled();
205 Features features();
206 bool isValidFileId(FileId fileId);
207 std::string toString(FileId fileId);
208 IncFsFileId toFileId(std::string_view str);
209 bool isIncFsFd(int fd);
210 bool isIncFsPath(std::string_view path);
211 
212 UniqueControl mount(std::string_view backingPath, std::string_view targetDir,
213                     IncFsMountOptions options);
214 UniqueControl open(std::string_view dir);
215 UniqueControl createControl(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs, IncFsFd blocksWritten);
216 
217 ErrorCode setOptions(const Control& control, MountOptions newOptions);
218 
219 ErrorCode bindMount(std::string_view sourceDir, std::string_view targetDir);
220 ErrorCode unmount(std::string_view dir);
221 
222 std::string root(const Control& control);
223 
224 ErrorCode makeFile(const Control& control, std::string_view path, int mode, FileId fileId,
225                    NewFileParams params);
226 ErrorCode makeMappedFile(const Control& control, std::string_view path, int mode,
227                          NewMappedFileParams params);
228 ErrorCode makeDir(const Control& control, std::string_view path, int mode = 0555);
229 ErrorCode makeDirs(const Control& control, std::string_view path, int mode = 0555);
230 
231 RawMetadata getMetadata(const Control& control, FileId fileId);
232 RawMetadata getMetadata(const Control& control, std::string_view path);
233 FileId getFileId(const Control& control, std::string_view path);
234 
235 RawSignature getSignature(const Control& control, FileId fileId);
236 RawSignature getSignature(const Control& control, std::string_view path);
237 
238 ErrorCode link(const Control& control, std::string_view sourcePath, std::string_view targetPath);
239 ErrorCode unlink(const Control& control, std::string_view path);
240 
241 enum class WaitResult { HaveData, Timeout, Error };
242 
243 WaitResult waitForPendingReads(const Control& control, std::chrono::milliseconds timeout,
244                                std::vector<ReadInfo>* pendingReadsBuffer);
245 WaitResult waitForPageReads(const Control& control, std::chrono::milliseconds timeout,
246                             std::vector<ReadInfo>* pageReadsBuffer);
247 WaitResult waitForPendingReads(const Control& control, std::chrono::milliseconds timeout,
248                                std::vector<ReadInfoWithUid>* pendingReadsBuffer);
249 WaitResult waitForPageReads(const Control& control, std::chrono::milliseconds timeout,
250                             std::vector<ReadInfoWithUid>* pageReadsBuffer);
251 
252 UniqueFd openForSpecialOps(const Control& control, FileId fileId);
253 UniqueFd openForSpecialOps(const Control& control, std::string_view path);
254 ErrorCode writeBlocks(Span<const DataBlock> blocks);
255 
256 std::pair<ErrorCode, FilledRanges> getFilledRanges(int fd);
257 std::pair<ErrorCode, FilledRanges> getFilledRanges(int fd, FilledRanges::RangeBuffer&& buffer);
258 std::pair<ErrorCode, FilledRanges> getFilledRanges(int fd, FilledRanges&& resumeFrom);
259 
260 ErrorCode setUidReadTimeouts(const Control& control, Span<const UidReadTimeouts> timeouts);
261 std::optional<std::vector<UidReadTimeouts>> getUidReadTimeouts(const Control& control);
262 
263 std::optional<BlockCounts> getBlockCount(const Control& control, FileId fileId);
264 std::optional<BlockCounts> getBlockCount(const Control& control, std::string_view path);
265 
266 std::optional<std::vector<FileId>> listIncompleteFiles(const Control& control);
267 
268 template <class Callback>
269 ErrorCode forEachFile(const Control& control, Callback&& cb);
270 template <class Callback>
271 ErrorCode forEachIncompleteFile(const Control& control, Callback&& cb);
272 
273 WaitResult waitForLoadingComplete(const Control& control, std::chrono::milliseconds timeout);
274 
275 enum class LoadingState { Full, MissingBlocks };
276 LoadingState isFullyLoaded(int fd);
277 LoadingState isFullyLoaded(const Control& control, std::string_view path);
278 LoadingState isFullyLoaded(const Control& control, FileId fileId);
279 LoadingState isEverythingFullyLoaded(const Control& control);
280 
281 static const auto kTrimReservedSpace = kIncFsTrimReservedSpace;
282 ErrorCode reserveSpace(const Control& control, std::string_view path, Size size);
283 ErrorCode reserveSpace(const Control& control, FileId id, Size size);
284 
285 std::optional<Metrics> getMetrics(std::string_view sysfsName);
286 std::optional<LastReadError> getLastReadError(const Control& control);
287 
288 // Some internal secret API as well that's not backed by C API yet.
289 class MountRegistry;
290 MountRegistry& defaultMountRegistry();
291 
292 } // namespace android::incfs
293 
294 bool operator==(const IncFsFileId& l, const IncFsFileId& r);
295 inline bool operator!=(const IncFsFileId& l, const IncFsFileId& r) {
296     return !(l == r);
297 }
298 
299 namespace std {
300 
301 template <>
302 struct hash<IncFsFileId> {
303     size_t operator()(const IncFsFileId& id) const noexcept {
304         return std::hash<std::string_view>()({&id.data[0], sizeof(id)});
305     }
306 };
307 
308 } // namespace std
309 
310 #include "incfs_inline.h"
311