xref: /aosp_15_r20/system/incremental_delivery/incfs/include/incfs_inline.h (revision 9190c2a8bd3622b7aa9bd7bfe4b3aec77820f478)
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