1*9190c2a8SAndroid Build Coastguard Worker /*
2*9190c2a8SAndroid Build Coastguard Worker * Copyright (C) 2019 The Android Open Source Project
3*9190c2a8SAndroid Build Coastguard Worker *
4*9190c2a8SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*9190c2a8SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*9190c2a8SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*9190c2a8SAndroid Build Coastguard Worker *
8*9190c2a8SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*9190c2a8SAndroid Build Coastguard Worker *
10*9190c2a8SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*9190c2a8SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*9190c2a8SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*9190c2a8SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*9190c2a8SAndroid Build Coastguard Worker * limitations under the License.
15*9190c2a8SAndroid Build Coastguard Worker */
16*9190c2a8SAndroid Build Coastguard Worker #pragma once
17*9190c2a8SAndroid Build Coastguard Worker
18*9190c2a8SAndroid Build Coastguard Worker #include <errno.h>
19*9190c2a8SAndroid Build Coastguard Worker
20*9190c2a8SAndroid Build Coastguard Worker #include <optional>
21*9190c2a8SAndroid Build Coastguard Worker #include <string>
22*9190c2a8SAndroid Build Coastguard Worker
23*9190c2a8SAndroid Build Coastguard Worker #include "incfs.h"
24*9190c2a8SAndroid Build Coastguard Worker
25*9190c2a8SAndroid Build Coastguard Worker namespace android::incfs {
26*9190c2a8SAndroid Build Coastguard Worker
27*9190c2a8SAndroid Build Coastguard Worker constexpr char kIdAttrName[] = INCFS_XATTR_ID_NAME;
28*9190c2a8SAndroid Build Coastguard Worker constexpr char kSizeAttrName[] = INCFS_XATTR_SIZE_NAME;
29*9190c2a8SAndroid Build Coastguard Worker constexpr char kMetadataAttrName[] = INCFS_XATTR_METADATA_NAME;
30*9190c2a8SAndroid Build Coastguard Worker
31*9190c2a8SAndroid Build Coastguard Worker extern const size_t kPageSize;
32*9190c2a8SAndroid Build Coastguard Worker
33*9190c2a8SAndroid Build Coastguard Worker namespace details {
34*9190c2a8SAndroid Build Coastguard Worker
35*9190c2a8SAndroid Build Coastguard Worker class CStrWrapper {
36*9190c2a8SAndroid Build Coastguard Worker public:
CStrWrapper(std::string_view sv)37*9190c2a8SAndroid Build Coastguard Worker CStrWrapper(std::string_view sv) {
38*9190c2a8SAndroid Build Coastguard Worker if (!sv.data()) {
39*9190c2a8SAndroid Build Coastguard Worker mCstr = "";
40*9190c2a8SAndroid Build Coastguard Worker } else if (sv[sv.size()] == '\0') {
41*9190c2a8SAndroid Build Coastguard Worker mCstr = sv.data();
42*9190c2a8SAndroid Build Coastguard Worker } else {
43*9190c2a8SAndroid Build Coastguard Worker mCopy.emplace(sv);
44*9190c2a8SAndroid Build Coastguard Worker mCstr = mCopy->c_str();
45*9190c2a8SAndroid Build Coastguard Worker }
46*9190c2a8SAndroid Build Coastguard Worker }
47*9190c2a8SAndroid Build Coastguard Worker
48*9190c2a8SAndroid Build Coastguard Worker CStrWrapper(const CStrWrapper&) = delete;
49*9190c2a8SAndroid Build Coastguard Worker void operator=(const CStrWrapper&) = delete;
50*9190c2a8SAndroid Build Coastguard Worker CStrWrapper(CStrWrapper&&) = delete;
51*9190c2a8SAndroid Build Coastguard Worker void operator=(CStrWrapper&&) = delete;
52*9190c2a8SAndroid Build Coastguard Worker
get()53*9190c2a8SAndroid Build Coastguard Worker const char* get() const { return mCstr; }
54*9190c2a8SAndroid Build Coastguard Worker operator const char*() const { return get(); }
55*9190c2a8SAndroid Build Coastguard Worker
56*9190c2a8SAndroid Build Coastguard Worker private:
57*9190c2a8SAndroid Build Coastguard Worker const char* mCstr;
58*9190c2a8SAndroid Build Coastguard Worker std::optional<std::string> mCopy;
59*9190c2a8SAndroid Build Coastguard Worker };
60*9190c2a8SAndroid Build Coastguard Worker
c_str(std::string_view sv)61*9190c2a8SAndroid Build Coastguard Worker inline CStrWrapper c_str(std::string_view sv) {
62*9190c2a8SAndroid Build Coastguard Worker return {sv};
63*9190c2a8SAndroid Build Coastguard Worker }
64*9190c2a8SAndroid Build Coastguard Worker
65*9190c2a8SAndroid Build Coastguard Worker } // namespace details
66*9190c2a8SAndroid Build Coastguard Worker
enabled()67*9190c2a8SAndroid Build Coastguard Worker inline bool enabled() {
68*9190c2a8SAndroid Build Coastguard Worker return IncFs_IsEnabled();
69*9190c2a8SAndroid Build Coastguard Worker }
70*9190c2a8SAndroid Build Coastguard Worker
features()71*9190c2a8SAndroid Build Coastguard Worker inline Features features() {
72*9190c2a8SAndroid Build Coastguard Worker return Features(IncFs_Features());
73*9190c2a8SAndroid Build Coastguard Worker }
74*9190c2a8SAndroid Build Coastguard Worker
isIncFsFd(int fd)75*9190c2a8SAndroid Build Coastguard Worker inline bool isIncFsFd(int fd) {
76*9190c2a8SAndroid Build Coastguard Worker return IncFs_IsIncFsFd(fd);
77*9190c2a8SAndroid Build Coastguard Worker }
78*9190c2a8SAndroid Build Coastguard Worker
isIncFsPath(std::string_view path)79*9190c2a8SAndroid Build Coastguard Worker inline bool isIncFsPath(std::string_view path) {
80*9190c2a8SAndroid Build Coastguard Worker return IncFs_IsIncFsPath(details::c_str(path));
81*9190c2a8SAndroid Build Coastguard Worker }
82*9190c2a8SAndroid Build Coastguard Worker
isValidFileId(FileId fileId)83*9190c2a8SAndroid Build Coastguard Worker inline bool isValidFileId(FileId fileId) {
84*9190c2a8SAndroid Build Coastguard Worker return IncFs_IsValidFileId(fileId);
85*9190c2a8SAndroid Build Coastguard Worker }
86*9190c2a8SAndroid Build Coastguard Worker
toString(FileId fileId)87*9190c2a8SAndroid Build Coastguard Worker inline std::string toString(FileId fileId) {
88*9190c2a8SAndroid Build Coastguard Worker std::string res(kIncFsFileIdStringLength, '\0');
89*9190c2a8SAndroid Build Coastguard Worker auto err = IncFs_FileIdToString(fileId, res.data());
90*9190c2a8SAndroid Build Coastguard Worker if (err) {
91*9190c2a8SAndroid Build Coastguard Worker errno = err;
92*9190c2a8SAndroid Build Coastguard Worker return {};
93*9190c2a8SAndroid Build Coastguard Worker }
94*9190c2a8SAndroid Build Coastguard Worker return res;
95*9190c2a8SAndroid Build Coastguard Worker }
96*9190c2a8SAndroid Build Coastguard Worker
toFileId(std::string_view str)97*9190c2a8SAndroid Build Coastguard Worker inline IncFsFileId toFileId(std::string_view str) {
98*9190c2a8SAndroid Build Coastguard Worker if (str.size() != kIncFsFileIdStringLength) {
99*9190c2a8SAndroid Build Coastguard Worker return kIncFsInvalidFileId;
100*9190c2a8SAndroid Build Coastguard Worker }
101*9190c2a8SAndroid Build Coastguard Worker return IncFs_FileIdFromString(str.data());
102*9190c2a8SAndroid Build Coastguard Worker }
103*9190c2a8SAndroid Build Coastguard Worker
close()104*9190c2a8SAndroid Build Coastguard Worker inline void UniqueControl::close() {
105*9190c2a8SAndroid Build Coastguard Worker IncFs_DeleteControl(mControl);
106*9190c2a8SAndroid Build Coastguard Worker mControl = nullptr;
107*9190c2a8SAndroid Build Coastguard Worker }
108*9190c2a8SAndroid Build Coastguard Worker
cmd()109*9190c2a8SAndroid Build Coastguard Worker inline IncFsFd UniqueControl::cmd() const {
110*9190c2a8SAndroid Build Coastguard Worker return IncFs_GetControlFd(mControl, CMD);
111*9190c2a8SAndroid Build Coastguard Worker }
112*9190c2a8SAndroid Build Coastguard Worker
pendingReads()113*9190c2a8SAndroid Build Coastguard Worker inline IncFsFd UniqueControl::pendingReads() const {
114*9190c2a8SAndroid Build Coastguard Worker return IncFs_GetControlFd(mControl, PENDING_READS);
115*9190c2a8SAndroid Build Coastguard Worker }
116*9190c2a8SAndroid Build Coastguard Worker
logs()117*9190c2a8SAndroid Build Coastguard Worker inline IncFsFd UniqueControl::logs() const {
118*9190c2a8SAndroid Build Coastguard Worker return IncFs_GetControlFd(mControl, LOGS);
119*9190c2a8SAndroid Build Coastguard Worker }
120*9190c2a8SAndroid Build Coastguard Worker
blocksWritten()121*9190c2a8SAndroid Build Coastguard Worker inline IncFsFd UniqueControl::blocksWritten() const {
122*9190c2a8SAndroid Build Coastguard Worker return IncFs_GetControlFd(mControl, BLOCKS_WRITTEN);
123*9190c2a8SAndroid Build Coastguard Worker }
124*9190c2a8SAndroid Build Coastguard Worker
releaseFds()125*9190c2a8SAndroid Build Coastguard Worker inline UniqueControl::Fds UniqueControl::releaseFds() {
126*9190c2a8SAndroid Build Coastguard Worker Fds result;
127*9190c2a8SAndroid Build Coastguard Worker IncFsFd fds[result.size()];
128*9190c2a8SAndroid Build Coastguard Worker auto count = IncFs_ReleaseControlFds(mControl, fds, std::size(fds));
129*9190c2a8SAndroid Build Coastguard Worker for (auto i = 0; i < count; ++i) {
130*9190c2a8SAndroid Build Coastguard Worker result[i] = UniqueFd(fds[i]);
131*9190c2a8SAndroid Build Coastguard Worker }
132*9190c2a8SAndroid Build Coastguard Worker return result;
133*9190c2a8SAndroid Build Coastguard Worker }
134*9190c2a8SAndroid Build Coastguard Worker
mount(std::string_view backingPath,std::string_view targetDir,MountOptions options)135*9190c2a8SAndroid Build Coastguard Worker inline UniqueControl mount(std::string_view backingPath, std::string_view targetDir,
136*9190c2a8SAndroid Build Coastguard Worker MountOptions options) {
137*9190c2a8SAndroid Build Coastguard Worker auto control = IncFs_Mount(details::c_str(backingPath), details::c_str(targetDir), options);
138*9190c2a8SAndroid Build Coastguard Worker return UniqueControl(control);
139*9190c2a8SAndroid Build Coastguard Worker }
140*9190c2a8SAndroid Build Coastguard Worker
open(std::string_view dir)141*9190c2a8SAndroid Build Coastguard Worker inline UniqueControl open(std::string_view dir) {
142*9190c2a8SAndroid Build Coastguard Worker auto control = IncFs_Open(details::c_str(dir));
143*9190c2a8SAndroid Build Coastguard Worker return UniqueControl(control);
144*9190c2a8SAndroid Build Coastguard Worker }
145*9190c2a8SAndroid Build Coastguard Worker
createControl(IncFsFd cmd,IncFsFd pendingReads,IncFsFd logs,IncFsFd blocksWritten)146*9190c2a8SAndroid Build Coastguard Worker inline UniqueControl createControl(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs,
147*9190c2a8SAndroid Build Coastguard Worker IncFsFd blocksWritten) {
148*9190c2a8SAndroid Build Coastguard Worker return UniqueControl(IncFs_CreateControl(cmd, pendingReads, logs, blocksWritten));
149*9190c2a8SAndroid Build Coastguard Worker }
150*9190c2a8SAndroid Build Coastguard Worker
setOptions(const Control & control,MountOptions newOptions)151*9190c2a8SAndroid Build Coastguard Worker inline ErrorCode setOptions(const Control& control, MountOptions newOptions) {
152*9190c2a8SAndroid Build Coastguard Worker return IncFs_SetOptions(control, newOptions);
153*9190c2a8SAndroid Build Coastguard Worker }
154*9190c2a8SAndroid Build Coastguard Worker
bindMount(std::string_view sourceDir,std::string_view targetDir)155*9190c2a8SAndroid Build Coastguard Worker inline ErrorCode bindMount(std::string_view sourceDir, std::string_view targetDir) {
156*9190c2a8SAndroid Build Coastguard Worker return IncFs_BindMount(details::c_str(sourceDir), details::c_str(targetDir));
157*9190c2a8SAndroid Build Coastguard Worker }
158*9190c2a8SAndroid Build Coastguard Worker
unmount(std::string_view dir)159*9190c2a8SAndroid Build Coastguard Worker inline ErrorCode unmount(std::string_view dir) {
160*9190c2a8SAndroid Build Coastguard Worker return IncFs_Unmount(details::c_str(dir));
161*9190c2a8SAndroid Build Coastguard Worker }
162*9190c2a8SAndroid Build Coastguard Worker
root(const Control & control)163*9190c2a8SAndroid Build Coastguard Worker inline std::string root(const Control& control) {
164*9190c2a8SAndroid Build Coastguard Worker std::string result;
165*9190c2a8SAndroid Build Coastguard Worker result.resize(PATH_MAX);
166*9190c2a8SAndroid Build Coastguard Worker size_t size = result.size();
167*9190c2a8SAndroid Build Coastguard Worker if (auto err = IncFs_Root(control, result.data(), &size); err < 0) {
168*9190c2a8SAndroid Build Coastguard Worker errno = -err;
169*9190c2a8SAndroid Build Coastguard Worker return {};
170*9190c2a8SAndroid Build Coastguard Worker }
171*9190c2a8SAndroid Build Coastguard Worker result.resize(size);
172*9190c2a8SAndroid Build Coastguard Worker return result;
173*9190c2a8SAndroid Build Coastguard Worker }
174*9190c2a8SAndroid Build Coastguard Worker
makeFile(const Control & control,std::string_view path,int mode,FileId fileId,NewFileParams params)175*9190c2a8SAndroid Build Coastguard Worker inline ErrorCode makeFile(const Control& control, std::string_view path, int mode, FileId fileId,
176*9190c2a8SAndroid Build Coastguard Worker NewFileParams params) {
177*9190c2a8SAndroid Build Coastguard Worker return IncFs_MakeFile(control, details::c_str(path), mode, fileId, params);
178*9190c2a8SAndroid Build Coastguard Worker }
makeMappedFile(const Control & control,std::string_view path,int mode,NewMappedFileParams params)179*9190c2a8SAndroid Build Coastguard Worker inline ErrorCode makeMappedFile(const Control& control, std::string_view path, int mode,
180*9190c2a8SAndroid Build Coastguard Worker NewMappedFileParams params) {
181*9190c2a8SAndroid Build Coastguard Worker return IncFs_MakeMappedFile(control, details::c_str(path), mode, params);
182*9190c2a8SAndroid Build Coastguard Worker }
makeDir(const Control & control,std::string_view path,int mode)183*9190c2a8SAndroid Build Coastguard Worker inline ErrorCode makeDir(const Control& control, std::string_view path, int mode) {
184*9190c2a8SAndroid Build Coastguard Worker return IncFs_MakeDir(control, details::c_str(path), mode);
185*9190c2a8SAndroid Build Coastguard Worker }
makeDirs(const Control & control,std::string_view path,int mode)186*9190c2a8SAndroid Build Coastguard Worker inline ErrorCode makeDirs(const Control& control, std::string_view path, int mode) {
187*9190c2a8SAndroid Build Coastguard Worker return IncFs_MakeDirs(control, details::c_str(path), mode);
188*9190c2a8SAndroid Build Coastguard Worker }
189*9190c2a8SAndroid Build Coastguard Worker
getMetadata(const Control & control,FileId fileId)190*9190c2a8SAndroid Build Coastguard Worker inline RawMetadata getMetadata(const Control& control, FileId fileId) {
191*9190c2a8SAndroid Build Coastguard Worker RawMetadata metadata(INCFS_MAX_FILE_ATTR_SIZE);
192*9190c2a8SAndroid Build Coastguard Worker size_t size = metadata.size();
193*9190c2a8SAndroid Build Coastguard Worker if (IncFs_GetMetadataById(control, fileId, metadata.data(), &size) < 0) {
194*9190c2a8SAndroid Build Coastguard Worker return {};
195*9190c2a8SAndroid Build Coastguard Worker }
196*9190c2a8SAndroid Build Coastguard Worker metadata.resize(size);
197*9190c2a8SAndroid Build Coastguard Worker return metadata;
198*9190c2a8SAndroid Build Coastguard Worker }
199*9190c2a8SAndroid Build Coastguard Worker
getMetadata(const Control & control,std::string_view path)200*9190c2a8SAndroid Build Coastguard Worker inline RawMetadata getMetadata(const Control& control, std::string_view path) {
201*9190c2a8SAndroid Build Coastguard Worker RawMetadata metadata(INCFS_MAX_FILE_ATTR_SIZE);
202*9190c2a8SAndroid Build Coastguard Worker size_t size = metadata.size();
203*9190c2a8SAndroid Build Coastguard Worker if (IncFs_GetMetadataByPath(control, details::c_str(path), metadata.data(), &size) < 0) {
204*9190c2a8SAndroid Build Coastguard Worker return {};
205*9190c2a8SAndroid Build Coastguard Worker }
206*9190c2a8SAndroid Build Coastguard Worker metadata.resize(size);
207*9190c2a8SAndroid Build Coastguard Worker return metadata;
208*9190c2a8SAndroid Build Coastguard Worker }
209*9190c2a8SAndroid Build Coastguard Worker
getSignature(const Control & control,FileId fileId)210*9190c2a8SAndroid Build Coastguard Worker inline RawSignature getSignature(const Control& control, FileId fileId) {
211*9190c2a8SAndroid Build Coastguard Worker RawSignature signature(INCFS_MAX_SIGNATURE_SIZE);
212*9190c2a8SAndroid Build Coastguard Worker size_t size = signature.size();
213*9190c2a8SAndroid Build Coastguard Worker if (IncFs_GetSignatureById(control, fileId, signature.data(), &size) < 0) {
214*9190c2a8SAndroid Build Coastguard Worker return {};
215*9190c2a8SAndroid Build Coastguard Worker }
216*9190c2a8SAndroid Build Coastguard Worker signature.resize(size);
217*9190c2a8SAndroid Build Coastguard Worker return signature;
218*9190c2a8SAndroid Build Coastguard Worker }
219*9190c2a8SAndroid Build Coastguard Worker
getSignature(const Control & control,std::string_view path)220*9190c2a8SAndroid Build Coastguard Worker inline RawSignature getSignature(const Control& control, std::string_view path) {
221*9190c2a8SAndroid Build Coastguard Worker RawSignature signature(INCFS_MAX_SIGNATURE_SIZE);
222*9190c2a8SAndroid Build Coastguard Worker size_t size = signature.size();
223*9190c2a8SAndroid Build Coastguard Worker if (IncFs_GetSignatureByPath(control, details::c_str(path), signature.data(), &size) < 0) {
224*9190c2a8SAndroid Build Coastguard Worker return {};
225*9190c2a8SAndroid Build Coastguard Worker }
226*9190c2a8SAndroid Build Coastguard Worker signature.resize(size);
227*9190c2a8SAndroid Build Coastguard Worker return signature;
228*9190c2a8SAndroid Build Coastguard Worker }
229*9190c2a8SAndroid Build Coastguard Worker
getFileId(const Control & control,std::string_view path)230*9190c2a8SAndroid Build Coastguard Worker inline FileId getFileId(const Control& control, std::string_view path) {
231*9190c2a8SAndroid Build Coastguard Worker return IncFs_GetId(control, details::c_str(path));
232*9190c2a8SAndroid Build Coastguard Worker }
233*9190c2a8SAndroid Build Coastguard Worker
link(const Control & control,std::string_view sourcePath,std::string_view targetPath)234*9190c2a8SAndroid Build Coastguard Worker inline ErrorCode link(const Control& control, std::string_view sourcePath,
235*9190c2a8SAndroid Build Coastguard Worker std::string_view targetPath) {
236*9190c2a8SAndroid Build Coastguard Worker return IncFs_Link(control, details::c_str(sourcePath), details::c_str(targetPath));
237*9190c2a8SAndroid Build Coastguard Worker }
238*9190c2a8SAndroid Build Coastguard Worker
unlink(const Control & control,std::string_view path)239*9190c2a8SAndroid Build Coastguard Worker inline ErrorCode unlink(const Control& control, std::string_view path) {
240*9190c2a8SAndroid Build Coastguard Worker return IncFs_Unlink(control, details::c_str(path));
241*9190c2a8SAndroid Build Coastguard Worker }
242*9190c2a8SAndroid Build Coastguard Worker
243*9190c2a8SAndroid Build Coastguard Worker template <class ReadInfoStruct, class Impl>
waitForReads(const Control & control,std::chrono::milliseconds timeout,std::vector<ReadInfoStruct> * pendingReadsBuffer,size_t defaultBufferSize,Impl impl)244*9190c2a8SAndroid Build Coastguard Worker WaitResult waitForReads(const Control& control, std::chrono::milliseconds timeout,
245*9190c2a8SAndroid Build Coastguard Worker std::vector<ReadInfoStruct>* pendingReadsBuffer, size_t defaultBufferSize,
246*9190c2a8SAndroid Build Coastguard Worker Impl impl) {
247*9190c2a8SAndroid Build Coastguard Worker if (pendingReadsBuffer->empty()) {
248*9190c2a8SAndroid Build Coastguard Worker pendingReadsBuffer->resize(defaultBufferSize);
249*9190c2a8SAndroid Build Coastguard Worker }
250*9190c2a8SAndroid Build Coastguard Worker size_t size = pendingReadsBuffer->size();
251*9190c2a8SAndroid Build Coastguard Worker IncFsErrorCode err = impl(control, timeout.count(), pendingReadsBuffer->data(), &size);
252*9190c2a8SAndroid Build Coastguard Worker pendingReadsBuffer->resize(size);
253*9190c2a8SAndroid Build Coastguard Worker switch (err) {
254*9190c2a8SAndroid Build Coastguard Worker case 0:
255*9190c2a8SAndroid Build Coastguard Worker return WaitResult::HaveData;
256*9190c2a8SAndroid Build Coastguard Worker case -ETIMEDOUT:
257*9190c2a8SAndroid Build Coastguard Worker return WaitResult::Timeout;
258*9190c2a8SAndroid Build Coastguard Worker }
259*9190c2a8SAndroid Build Coastguard Worker return WaitResult(err);
260*9190c2a8SAndroid Build Coastguard Worker }
261*9190c2a8SAndroid Build Coastguard Worker
waitForPendingReads(const Control & control,std::chrono::milliseconds timeout,std::vector<ReadInfo> * pendingReadsBuffer)262*9190c2a8SAndroid Build Coastguard Worker inline WaitResult waitForPendingReads(const Control& control, std::chrono::milliseconds timeout,
263*9190c2a8SAndroid Build Coastguard Worker std::vector<ReadInfo>* pendingReadsBuffer) {
264*9190c2a8SAndroid Build Coastguard Worker return waitForReads(control, timeout, pendingReadsBuffer,
265*9190c2a8SAndroid Build Coastguard Worker INCFS_DEFAULT_PENDING_READ_BUFFER_SIZE, IncFs_WaitForPendingReads);
266*9190c2a8SAndroid Build Coastguard Worker }
267*9190c2a8SAndroid Build Coastguard Worker
waitForPendingReads(const Control & control,std::chrono::milliseconds timeout,std::vector<ReadInfoWithUid> * pendingReadsBuffer)268*9190c2a8SAndroid Build Coastguard Worker inline WaitResult waitForPendingReads(const Control& control, std::chrono::milliseconds timeout,
269*9190c2a8SAndroid Build Coastguard Worker std::vector<ReadInfoWithUid>* pendingReadsBuffer) {
270*9190c2a8SAndroid Build Coastguard Worker return waitForReads(control, timeout, pendingReadsBuffer,
271*9190c2a8SAndroid Build Coastguard Worker INCFS_DEFAULT_PENDING_READ_BUFFER_SIZE, IncFs_WaitForPendingReadsWithUid);
272*9190c2a8SAndroid Build Coastguard Worker }
273*9190c2a8SAndroid Build Coastguard Worker
waitForPageReads(const Control & control,std::chrono::milliseconds timeout,std::vector<ReadInfo> * pageReadsBuffer)274*9190c2a8SAndroid Build Coastguard Worker inline WaitResult waitForPageReads(const Control& control, std::chrono::milliseconds timeout,
275*9190c2a8SAndroid Build Coastguard Worker std::vector<ReadInfo>* pageReadsBuffer) {
276*9190c2a8SAndroid Build Coastguard Worker static const auto kDefaultBufferSize =
277*9190c2a8SAndroid Build Coastguard Worker INCFS_DEFAULT_PAGE_READ_BUFFER_PAGES * kPageSize / sizeof(ReadInfo);
278*9190c2a8SAndroid Build Coastguard Worker return waitForReads(control, timeout, pageReadsBuffer, kDefaultBufferSize,
279*9190c2a8SAndroid Build Coastguard Worker IncFs_WaitForPageReads);
280*9190c2a8SAndroid Build Coastguard Worker }
281*9190c2a8SAndroid Build Coastguard Worker
waitForPageReads(const Control & control,std::chrono::milliseconds timeout,std::vector<ReadInfoWithUid> * pageReadsBuffer)282*9190c2a8SAndroid Build Coastguard Worker inline WaitResult waitForPageReads(const Control& control, std::chrono::milliseconds timeout,
283*9190c2a8SAndroid Build Coastguard Worker std::vector<ReadInfoWithUid>* pageReadsBuffer) {
284*9190c2a8SAndroid Build Coastguard Worker static const auto kDefaultBufferSize =
285*9190c2a8SAndroid Build Coastguard Worker INCFS_DEFAULT_PAGE_READ_BUFFER_PAGES * kPageSize / sizeof(ReadInfoWithUid);
286*9190c2a8SAndroid Build Coastguard Worker return waitForReads(control, timeout, pageReadsBuffer, kDefaultBufferSize,
287*9190c2a8SAndroid Build Coastguard Worker IncFs_WaitForPageReadsWithUid);
288*9190c2a8SAndroid Build Coastguard Worker }
289*9190c2a8SAndroid Build Coastguard Worker
openForSpecialOps(const Control & control,FileId fileId)290*9190c2a8SAndroid Build Coastguard Worker inline UniqueFd openForSpecialOps(const Control& control, FileId fileId) {
291*9190c2a8SAndroid Build Coastguard Worker return UniqueFd(IncFs_OpenForSpecialOpsById(control, fileId));
292*9190c2a8SAndroid Build Coastguard Worker }
openForSpecialOps(const Control & control,std::string_view path)293*9190c2a8SAndroid Build Coastguard Worker inline UniqueFd openForSpecialOps(const Control& control, std::string_view path) {
294*9190c2a8SAndroid Build Coastguard Worker return UniqueFd(IncFs_OpenForSpecialOpsByPath(control, details::c_str(path)));
295*9190c2a8SAndroid Build Coastguard Worker }
296*9190c2a8SAndroid Build Coastguard Worker
writeBlocks(Span<const DataBlock> blocks)297*9190c2a8SAndroid Build Coastguard Worker inline ErrorCode writeBlocks(Span<const DataBlock> blocks) {
298*9190c2a8SAndroid Build Coastguard Worker return IncFs_WriteBlocks(blocks.data(), blocks.size());
299*9190c2a8SAndroid Build Coastguard Worker }
300*9190c2a8SAndroid Build Coastguard Worker
getFilledRanges(int fd)301*9190c2a8SAndroid Build Coastguard Worker inline std::pair<ErrorCode, FilledRanges> getFilledRanges(int fd) {
302*9190c2a8SAndroid Build Coastguard Worker return getFilledRanges(fd, FilledRanges());
303*9190c2a8SAndroid Build Coastguard Worker }
304*9190c2a8SAndroid Build Coastguard Worker
getFilledRanges(int fd,FilledRanges::RangeBuffer && buffer)305*9190c2a8SAndroid Build Coastguard Worker inline std::pair<ErrorCode, FilledRanges> getFilledRanges(int fd,
306*9190c2a8SAndroid Build Coastguard Worker FilledRanges::RangeBuffer&& buffer) {
307*9190c2a8SAndroid Build Coastguard Worker return getFilledRanges(fd, FilledRanges(std::move(buffer), {}));
308*9190c2a8SAndroid Build Coastguard Worker }
309*9190c2a8SAndroid Build Coastguard Worker
getFilledRanges(int fd,FilledRanges && resumeFrom)310*9190c2a8SAndroid Build Coastguard Worker inline std::pair<ErrorCode, FilledRanges> getFilledRanges(int fd, FilledRanges&& resumeFrom) {
311*9190c2a8SAndroid Build Coastguard Worker auto totalRanges = resumeFrom.dataRanges().size() + resumeFrom.hashRanges().size();
312*9190c2a8SAndroid Build Coastguard Worker auto rawRanges = resumeFrom.internalRawRanges();
313*9190c2a8SAndroid Build Coastguard Worker auto buffer = resumeFrom.extractInternalBufferAndClear();
314*9190c2a8SAndroid Build Coastguard Worker auto remainingSpace = buffer.size() - totalRanges;
315*9190c2a8SAndroid Build Coastguard Worker const bool loadAll = remainingSpace == 0;
316*9190c2a8SAndroid Build Coastguard Worker int res;
317*9190c2a8SAndroid Build Coastguard Worker do {
318*9190c2a8SAndroid Build Coastguard Worker if (remainingSpace == 0) {
319*9190c2a8SAndroid Build Coastguard Worker remainingSpace = std::max<size_t>(32, buffer.size() / 2);
320*9190c2a8SAndroid Build Coastguard Worker buffer.resize(buffer.size() + remainingSpace);
321*9190c2a8SAndroid Build Coastguard Worker }
322*9190c2a8SAndroid Build Coastguard Worker auto outBuffer = IncFsSpan{(const char*)(buffer.data() + rawRanges.dataRangesCount +
323*9190c2a8SAndroid Build Coastguard Worker rawRanges.hashRangesCount),
324*9190c2a8SAndroid Build Coastguard Worker IncFsSize(remainingSpace * sizeof(buffer[0]))};
325*9190c2a8SAndroid Build Coastguard Worker IncFsFilledRanges newRanges;
326*9190c2a8SAndroid Build Coastguard Worker res = IncFs_GetFilledRangesStartingFrom(fd, rawRanges.endIndex, outBuffer, &newRanges);
327*9190c2a8SAndroid Build Coastguard Worker if (res && res != -ERANGE) {
328*9190c2a8SAndroid Build Coastguard Worker return {res, FilledRanges(std::move(buffer), {})};
329*9190c2a8SAndroid Build Coastguard Worker }
330*9190c2a8SAndroid Build Coastguard Worker
331*9190c2a8SAndroid Build Coastguard Worker rawRanges.dataRangesCount += newRanges.dataRangesCount;
332*9190c2a8SAndroid Build Coastguard Worker rawRanges.hashRangesCount += newRanges.hashRangesCount;
333*9190c2a8SAndroid Build Coastguard Worker rawRanges.endIndex = newRanges.endIndex;
334*9190c2a8SAndroid Build Coastguard Worker remainingSpace = buffer.size() - rawRanges.dataRangesCount - rawRanges.hashRangesCount;
335*9190c2a8SAndroid Build Coastguard Worker } while (res && loadAll);
336*9190c2a8SAndroid Build Coastguard Worker
337*9190c2a8SAndroid Build Coastguard Worker rawRanges.dataRanges = buffer.data();
338*9190c2a8SAndroid Build Coastguard Worker rawRanges.hashRanges = buffer.data() + rawRanges.dataRangesCount;
339*9190c2a8SAndroid Build Coastguard Worker return {res, FilledRanges(std::move(buffer), rawRanges)};
340*9190c2a8SAndroid Build Coastguard Worker }
341*9190c2a8SAndroid Build Coastguard Worker
toLoadingState(IncFsErrorCode res)342*9190c2a8SAndroid Build Coastguard Worker inline LoadingState toLoadingState(IncFsErrorCode res) {
343*9190c2a8SAndroid Build Coastguard Worker switch (res) {
344*9190c2a8SAndroid Build Coastguard Worker case 0:
345*9190c2a8SAndroid Build Coastguard Worker return LoadingState::Full;
346*9190c2a8SAndroid Build Coastguard Worker case -ENODATA:
347*9190c2a8SAndroid Build Coastguard Worker return LoadingState::MissingBlocks;
348*9190c2a8SAndroid Build Coastguard Worker default:
349*9190c2a8SAndroid Build Coastguard Worker return LoadingState(res);
350*9190c2a8SAndroid Build Coastguard Worker }
351*9190c2a8SAndroid Build Coastguard Worker }
352*9190c2a8SAndroid Build Coastguard Worker
isFullyLoaded(int fd)353*9190c2a8SAndroid Build Coastguard Worker inline LoadingState isFullyLoaded(int fd) {
354*9190c2a8SAndroid Build Coastguard Worker return toLoadingState(IncFs_IsFullyLoaded(fd));
355*9190c2a8SAndroid Build Coastguard Worker }
isFullyLoaded(const Control & control,std::string_view path)356*9190c2a8SAndroid Build Coastguard Worker inline LoadingState isFullyLoaded(const Control& control, std::string_view path) {
357*9190c2a8SAndroid Build Coastguard Worker return toLoadingState(IncFs_IsFullyLoadedByPath(control, details::c_str(path)));
358*9190c2a8SAndroid Build Coastguard Worker }
isFullyLoaded(const Control & control,FileId fileId)359*9190c2a8SAndroid Build Coastguard Worker inline LoadingState isFullyLoaded(const Control& control, FileId fileId) {
360*9190c2a8SAndroid Build Coastguard Worker return toLoadingState(IncFs_IsFullyLoadedById(control, fileId));
361*9190c2a8SAndroid Build Coastguard Worker }
362*9190c2a8SAndroid Build Coastguard Worker
isEverythingFullyLoaded(const Control & control)363*9190c2a8SAndroid Build Coastguard Worker inline LoadingState isEverythingFullyLoaded(const Control& control) {
364*9190c2a8SAndroid Build Coastguard Worker return toLoadingState(IncFs_IsEverythingFullyLoaded(control));
365*9190c2a8SAndroid Build Coastguard Worker }
366*9190c2a8SAndroid Build Coastguard Worker
listIncompleteFiles(const Control & control)367*9190c2a8SAndroid Build Coastguard Worker inline std::optional<std::vector<FileId>> listIncompleteFiles(const Control& control) {
368*9190c2a8SAndroid Build Coastguard Worker std::vector<FileId> ids(32);
369*9190c2a8SAndroid Build Coastguard Worker size_t count = ids.size();
370*9190c2a8SAndroid Build Coastguard Worker auto err = IncFs_ListIncompleteFiles(control, ids.data(), &count);
371*9190c2a8SAndroid Build Coastguard Worker if (err == -E2BIG) {
372*9190c2a8SAndroid Build Coastguard Worker ids.resize(count);
373*9190c2a8SAndroid Build Coastguard Worker err = IncFs_ListIncompleteFiles(control, ids.data(), &count);
374*9190c2a8SAndroid Build Coastguard Worker }
375*9190c2a8SAndroid Build Coastguard Worker if (err) {
376*9190c2a8SAndroid Build Coastguard Worker errno = -err;
377*9190c2a8SAndroid Build Coastguard Worker return {};
378*9190c2a8SAndroid Build Coastguard Worker }
379*9190c2a8SAndroid Build Coastguard Worker ids.resize(count);
380*9190c2a8SAndroid Build Coastguard Worker return std::move(ids);
381*9190c2a8SAndroid Build Coastguard Worker }
382*9190c2a8SAndroid Build Coastguard Worker
383*9190c2a8SAndroid Build Coastguard Worker template <class Callback>
forEachFile(const Control & control,Callback && cb)384*9190c2a8SAndroid Build Coastguard Worker inline ErrorCode forEachFile(const Control& control, Callback&& cb) {
385*9190c2a8SAndroid Build Coastguard Worker struct Context {
386*9190c2a8SAndroid Build Coastguard Worker const Control& c;
387*9190c2a8SAndroid Build Coastguard Worker const Callback& cb;
388*9190c2a8SAndroid Build Coastguard Worker } context = {control, cb};
389*9190c2a8SAndroid Build Coastguard Worker return IncFs_ForEachFile(control, &context, [](void* pcontext, const IncFsControl*, FileId id) {
390*9190c2a8SAndroid Build Coastguard Worker const auto context = (Context*)pcontext;
391*9190c2a8SAndroid Build Coastguard Worker return context->cb(context->c, id);
392*9190c2a8SAndroid Build Coastguard Worker });
393*9190c2a8SAndroid Build Coastguard Worker }
394*9190c2a8SAndroid Build Coastguard Worker template <class Callback>
forEachIncompleteFile(const Control & control,Callback && cb)395*9190c2a8SAndroid Build Coastguard Worker inline ErrorCode forEachIncompleteFile(const Control& control, Callback&& cb) {
396*9190c2a8SAndroid Build Coastguard Worker struct Context {
397*9190c2a8SAndroid Build Coastguard Worker const Control& c;
398*9190c2a8SAndroid Build Coastguard Worker const Callback& cb;
399*9190c2a8SAndroid Build Coastguard Worker } context = {control, cb};
400*9190c2a8SAndroid Build Coastguard Worker return IncFs_ForEachIncompleteFile(control, &context,
401*9190c2a8SAndroid Build Coastguard Worker [](void* pcontext, const IncFsControl*, FileId id) {
402*9190c2a8SAndroid Build Coastguard Worker const auto context = (Context*)pcontext;
403*9190c2a8SAndroid Build Coastguard Worker return context->cb(context->c, id);
404*9190c2a8SAndroid Build Coastguard Worker });
405*9190c2a8SAndroid Build Coastguard Worker }
406*9190c2a8SAndroid Build Coastguard Worker
waitForLoadingComplete(const Control & control,std::chrono::milliseconds timeout)407*9190c2a8SAndroid Build Coastguard Worker inline WaitResult waitForLoadingComplete(const Control& control,
408*9190c2a8SAndroid Build Coastguard Worker std::chrono::milliseconds timeout) {
409*9190c2a8SAndroid Build Coastguard Worker const auto res = IncFs_WaitForLoadingComplete(control, timeout.count());
410*9190c2a8SAndroid Build Coastguard Worker switch (res) {
411*9190c2a8SAndroid Build Coastguard Worker case 0:
412*9190c2a8SAndroid Build Coastguard Worker return WaitResult::HaveData;
413*9190c2a8SAndroid Build Coastguard Worker case -ETIMEDOUT:
414*9190c2a8SAndroid Build Coastguard Worker return WaitResult::Timeout;
415*9190c2a8SAndroid Build Coastguard Worker default:
416*9190c2a8SAndroid Build Coastguard Worker return WaitResult(res);
417*9190c2a8SAndroid Build Coastguard Worker }
418*9190c2a8SAndroid Build Coastguard Worker }
419*9190c2a8SAndroid Build Coastguard Worker
getBlockCount(const Control & control,FileId fileId)420*9190c2a8SAndroid Build Coastguard Worker inline std::optional<BlockCounts> getBlockCount(const Control& control, FileId fileId) {
421*9190c2a8SAndroid Build Coastguard Worker BlockCounts counts;
422*9190c2a8SAndroid Build Coastguard Worker auto res = IncFs_GetFileBlockCountById(control, fileId, &counts);
423*9190c2a8SAndroid Build Coastguard Worker if (res) {
424*9190c2a8SAndroid Build Coastguard Worker errno = -res;
425*9190c2a8SAndroid Build Coastguard Worker return {};
426*9190c2a8SAndroid Build Coastguard Worker }
427*9190c2a8SAndroid Build Coastguard Worker return counts;
428*9190c2a8SAndroid Build Coastguard Worker }
429*9190c2a8SAndroid Build Coastguard Worker
getBlockCount(const Control & control,std::string_view path)430*9190c2a8SAndroid Build Coastguard Worker inline std::optional<BlockCounts> getBlockCount(const Control& control, std::string_view path) {
431*9190c2a8SAndroid Build Coastguard Worker BlockCounts counts;
432*9190c2a8SAndroid Build Coastguard Worker auto res = IncFs_GetFileBlockCountByPath(control, details::c_str(path), &counts);
433*9190c2a8SAndroid Build Coastguard Worker if (res) {
434*9190c2a8SAndroid Build Coastguard Worker errno = -res;
435*9190c2a8SAndroid Build Coastguard Worker return {};
436*9190c2a8SAndroid Build Coastguard Worker }
437*9190c2a8SAndroid Build Coastguard Worker return counts;
438*9190c2a8SAndroid Build Coastguard Worker }
439*9190c2a8SAndroid Build Coastguard Worker
setUidReadTimeouts(const Control & control,Span<const UidReadTimeouts> timeouts)440*9190c2a8SAndroid Build Coastguard Worker inline ErrorCode setUidReadTimeouts(const Control& control, Span<const UidReadTimeouts> timeouts) {
441*9190c2a8SAndroid Build Coastguard Worker return IncFs_SetUidReadTimeouts(control, timeouts.data(), timeouts.size());
442*9190c2a8SAndroid Build Coastguard Worker }
443*9190c2a8SAndroid Build Coastguard Worker
getUidReadTimeouts(const Control & control)444*9190c2a8SAndroid Build Coastguard Worker inline std::optional<std::vector<UidReadTimeouts>> getUidReadTimeouts(const Control& control) {
445*9190c2a8SAndroid Build Coastguard Worker std::vector<UidReadTimeouts> timeouts(32);
446*9190c2a8SAndroid Build Coastguard Worker size_t count = timeouts.size();
447*9190c2a8SAndroid Build Coastguard Worker auto res = IncFs_GetUidReadTimeouts(control, timeouts.data(), &count);
448*9190c2a8SAndroid Build Coastguard Worker if (res == -E2BIG) {
449*9190c2a8SAndroid Build Coastguard Worker timeouts.resize(count);
450*9190c2a8SAndroid Build Coastguard Worker res = IncFs_GetUidReadTimeouts(control, timeouts.data(), &count);
451*9190c2a8SAndroid Build Coastguard Worker }
452*9190c2a8SAndroid Build Coastguard Worker if (res) {
453*9190c2a8SAndroid Build Coastguard Worker errno = -res;
454*9190c2a8SAndroid Build Coastguard Worker return {};
455*9190c2a8SAndroid Build Coastguard Worker }
456*9190c2a8SAndroid Build Coastguard Worker timeouts.resize(count);
457*9190c2a8SAndroid Build Coastguard Worker return std::move(timeouts);
458*9190c2a8SAndroid Build Coastguard Worker }
459*9190c2a8SAndroid Build Coastguard Worker
reserveSpace(const Control & control,std::string_view path,Size size)460*9190c2a8SAndroid Build Coastguard Worker inline ErrorCode reserveSpace(const Control& control, std::string_view path, Size size) {
461*9190c2a8SAndroid Build Coastguard Worker return IncFs_ReserveSpaceByPath(control, details::c_str(path), size);
462*9190c2a8SAndroid Build Coastguard Worker }
reserveSpace(const Control & control,FileId id,Size size)463*9190c2a8SAndroid Build Coastguard Worker inline ErrorCode reserveSpace(const Control& control, FileId id, Size size) {
464*9190c2a8SAndroid Build Coastguard Worker return IncFs_ReserveSpaceById(control, id, size);
465*9190c2a8SAndroid Build Coastguard Worker }
466*9190c2a8SAndroid Build Coastguard Worker
getMetrics(std::string_view sysfsName)467*9190c2a8SAndroid Build Coastguard Worker inline std::optional<Metrics> getMetrics(std::string_view sysfsName) {
468*9190c2a8SAndroid Build Coastguard Worker Metrics metrics;
469*9190c2a8SAndroid Build Coastguard Worker if (const auto res = IncFs_GetMetrics(details::c_str(sysfsName), &metrics); res < 0) {
470*9190c2a8SAndroid Build Coastguard Worker errno = -res;
471*9190c2a8SAndroid Build Coastguard Worker return {};
472*9190c2a8SAndroid Build Coastguard Worker }
473*9190c2a8SAndroid Build Coastguard Worker return metrics;
474*9190c2a8SAndroid Build Coastguard Worker }
475*9190c2a8SAndroid Build Coastguard Worker
getLastReadError(const Control & control)476*9190c2a8SAndroid Build Coastguard Worker inline std::optional<LastReadError> getLastReadError(const Control& control) {
477*9190c2a8SAndroid Build Coastguard Worker LastReadError lastReadError;
478*9190c2a8SAndroid Build Coastguard Worker if (const auto res = IncFs_GetLastReadError(control, &lastReadError); res < 0) {
479*9190c2a8SAndroid Build Coastguard Worker errno = -res;
480*9190c2a8SAndroid Build Coastguard Worker return {};
481*9190c2a8SAndroid Build Coastguard Worker }
482*9190c2a8SAndroid Build Coastguard Worker return lastReadError;
483*9190c2a8SAndroid Build Coastguard Worker }
484*9190c2a8SAndroid Build Coastguard Worker
485*9190c2a8SAndroid Build Coastguard Worker } // namespace android::incfs
486*9190c2a8SAndroid Build Coastguard Worker
487*9190c2a8SAndroid Build Coastguard Worker inline bool operator==(const IncFsFileId& l, const IncFsFileId& r) {
488*9190c2a8SAndroid Build Coastguard Worker return memcmp(&l, &r, sizeof(l)) == 0;
489*9190c2a8SAndroid Build Coastguard Worker }
490