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 
17 #ifndef ANDROID_INCREMENTAL_FILE_SYSTEM_NDK_H
18 #define ANDROID_INCREMENTAL_FILE_SYSTEM_NDK_H
19 
20 #include <linux/incrementalfs.h>
21 #include <stdbool.h>
22 #include <stddef.h>
23 #include <stdint.h>
24 #include <string.h>
25 #include <sys/cdefs.h>
26 
27 __BEGIN_DECLS
28 
29 #define INCFS_LIBRARY_NAME "libincfs.so"
30 
31 typedef struct {
32     union {
33         char data[16];
34         int64_t for_alignment;
35     };
36 } IncFsFileId;
37 
38 static const IncFsFileId kIncFsInvalidFileId = {
39         {{(char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1,
40           (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1}}};
41 
42 static const int kIncFsFileIdStringLength = sizeof(IncFsFileId) * 2;
43 
44 typedef enum {
45     INCFS_FEATURE_NONE = 0,
46     INCFS_FEATURE_CORE = 1,
47     INCFS_FEATURE_V2 = 2,
48 } IncFsFeatures;
49 
50 typedef int IncFsErrorCode;
51 typedef int64_t IncFsSize;
52 typedef int32_t IncFsBlockIndex;
53 typedef int IncFsFd;
54 typedef struct IncFsControl IncFsControl;
55 typedef int IncFsUid;
56 
57 static const IncFsUid kIncFsNoUid = -1;
58 
59 typedef struct {
60     const char* data;
61     IncFsSize size;
62 } IncFsSpan;
63 
64 typedef enum {
65     CMD,
66     PENDING_READS,
67     LOGS,
68     BLOCKS_WRITTEN,
69     FDS_COUNT,
70 } IncFsFdType;
71 
72 typedef enum {
73     INCFS_DEFAULT_READ_TIMEOUT_MS = 10000,
74     INCFS_DEFAULT_PENDING_READ_BUFFER_SIZE = 24,
75     INCFS_DEFAULT_PAGE_READ_BUFFER_PAGES = 4,
76 } IncFsDefaults;
77 
78 typedef enum {
79     INCFS_MOUNT_CREATE_ONLY = 1,
80     INCFS_MOUNT_TRUNCATE = 2,
81 } IncFsMountFlags;
82 
83 typedef enum {
84     INCFS_HASH_NONE,
85     INCFS_HASH_SHA256,
86 } IncFsHashAlgortithm;
87 
88 typedef struct {
89     IncFsMountFlags flags;
90     int32_t defaultReadTimeoutMs;
91     int32_t readLogBufferPages;
92     int32_t readLogDisableAfterTimeoutMs;
93     const char* sysfsName;
94 } IncFsMountOptions;
95 
96 typedef enum {
97     INCFS_COMPRESSION_KIND_NONE,
98     INCFS_COMPRESSION_KIND_LZ4,
99     INCFS_COMPRESSION_KIND_ZSTD,
100 } IncFsCompressionKind;
101 
102 typedef enum {
103     INCFS_BLOCK_KIND_DATA,
104     INCFS_BLOCK_KIND_HASH,
105 } IncFsBlockKind;
106 
107 typedef struct {
108     IncFsFd fileFd;
109     IncFsBlockIndex pageIndex;
110     IncFsCompressionKind compression;
111     IncFsBlockKind kind;
112     uint32_t dataSize;
113     const char* data;
114 } IncFsDataBlock;
115 
116 typedef struct {
117     IncFsSize size;
118     IncFsSpan metadata;
119     IncFsSpan signature;
120 } IncFsNewFileParams;
121 
122 typedef struct {
123     IncFsFileId sourceId;
124     IncFsSize sourceOffset;
125     IncFsSize size;
126 } IncFsNewMappedFileParams;
127 
128 typedef struct {
129     IncFsFileId id;
130     uint64_t bootClockTsUs;
131     IncFsBlockIndex block;
132     uint32_t serialNo;
133 } IncFsReadInfo;
134 
135 typedef struct {
136     IncFsFileId id;
137     uint64_t bootClockTsUs;
138     IncFsBlockIndex block;
139     uint32_t serialNo;
140     IncFsUid uid;
141 } IncFsReadInfoWithUid;
142 
143 typedef struct {
144     IncFsBlockIndex begin;
145     IncFsBlockIndex end;
146 } IncFsBlockRange;
147 
148 typedef struct {
149     IncFsBlockRange* dataRanges;
150     IncFsBlockRange* hashRanges;
151     int32_t dataRangesCount;
152     int32_t hashRangesCount;
153     IncFsBlockIndex endIndex;
154 } IncFsFilledRanges;
155 
156 typedef struct {
157     IncFsSize totalDataBlocks;
158     IncFsSize filledDataBlocks;
159     IncFsSize totalHashBlocks;
160     IncFsSize filledHashBlocks;
161 } IncFsBlockCounts;
162 
163 typedef struct {
164     IncFsUid uid;
165     uint32_t minTimeUs;
166     uint32_t minPendingTimeUs;
167     uint32_t maxPendingTimeUs;
168 } IncFsUidReadTimeouts;
169 
170 typedef struct {
171     uint32_t readsDelayedMin;
172     uint64_t readsDelayedMinUs;
173     uint32_t readsDelayedPending;
174     uint64_t readsDelayedPendingUs;
175     uint32_t readsFailedHashVerification;
176     uint32_t readsFailedOther;
177     uint32_t readsFailedTimedOut;
178     uint64_t reserved;
179     uint64_t reserved1;
180 } IncFsMetrics;
181 
182 typedef struct {
183     IncFsFileId id;
184     uint64_t timestampUs;
185     IncFsBlockIndex block;
186     uint32_t errorNo;
187     IncFsUid uid;
188 } IncFsLastReadError;
189 
190 // All functions return -errno in case of failure.
191 // All IncFsFd functions return >=0 in case of success.
192 // All IncFsFileId functions return invalid IncFsFileId on error.
193 // All IncFsErrorCode functions return 0 in case of success.
194 
195 bool IncFs_IsEnabled();
196 IncFsFeatures IncFs_Features();
197 
198 bool IncFs_IsIncFsFd(int fd);
199 bool IncFs_IsIncFsPath(const char* path);
200 
IncFs_IsValidFileId(IncFsFileId fileId)201 static inline bool IncFs_IsValidFileId(IncFsFileId fileId) {
202     return memcmp(&fileId, &kIncFsInvalidFileId, sizeof(fileId)) != 0;
203 }
204 
205 int IncFs_FileIdToString(IncFsFileId id, char* out);
206 IncFsFileId IncFs_FileIdFromString(const char* in);
207 
208 IncFsFileId IncFs_FileIdFromMetadata(IncFsSpan metadata);
209 
210 IncFsControl* IncFs_Mount(const char* backingPath, const char* targetDir,
211                           IncFsMountOptions options);
212 IncFsControl* IncFs_Open(const char* dir);
213 IncFsControl* IncFs_CreateControl(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs,
214                                   IncFsFd blocksWritten);
215 void IncFs_DeleteControl(IncFsControl* control);
216 IncFsFd IncFs_GetControlFd(const IncFsControl* control, IncFsFdType type);
217 IncFsSize IncFs_ReleaseControlFds(IncFsControl* control, IncFsFd out[], IncFsSize outSize);
218 
219 IncFsErrorCode IncFs_SetOptions(const IncFsControl* control, IncFsMountOptions options);
220 
221 IncFsErrorCode IncFs_BindMount(const char* sourceDir, const char* targetDir);
222 IncFsErrorCode IncFs_Unmount(const char* dir);
223 
224 IncFsErrorCode IncFs_Root(const IncFsControl* control, char buffer[], size_t* bufferSize);
225 
226 IncFsErrorCode IncFs_MakeFile(const IncFsControl* control, const char* path, int32_t mode,
227                               IncFsFileId id, IncFsNewFileParams params);
228 IncFsErrorCode IncFs_MakeMappedFile(const IncFsControl* control, const char* path, int32_t mode,
229                                     IncFsNewMappedFileParams params);
230 
231 IncFsErrorCode IncFs_MakeDir(const IncFsControl* control, const char* path, int32_t mode);
232 IncFsErrorCode IncFs_MakeDirs(const IncFsControl* control, const char* path, int32_t mode);
233 
234 IncFsErrorCode IncFs_GetMetadataById(const IncFsControl* control, IncFsFileId id, char buffer[],
235                                      size_t* bufferSize);
236 IncFsErrorCode IncFs_GetMetadataByPath(const IncFsControl* control, const char* path, char buffer[],
237                                        size_t* bufferSize);
238 
239 IncFsErrorCode IncFs_GetSignatureById(const IncFsControl* control, IncFsFileId id, char buffer[],
240                                       size_t* bufferSize);
241 IncFsErrorCode IncFs_GetSignatureByPath(const IncFsControl* control, const char* path,
242                                         char buffer[], size_t* bufferSize);
243 IncFsErrorCode IncFs_UnsafeGetSignatureByPath(const char* path, char buffer[], size_t* bufferSize);
244 
245 IncFsFileId IncFs_GetId(const IncFsControl* control, const char* path);
246 
247 IncFsErrorCode IncFs_Link(const IncFsControl* control, const char* sourcePath,
248                           const char* targetPath);
249 IncFsErrorCode IncFs_Unlink(const IncFsControl* control, const char* path);
250 
251 IncFsErrorCode IncFs_WaitForPendingReads(const IncFsControl* control, int32_t timeoutMs,
252                                          IncFsReadInfo buffer[], size_t* bufferSize);
253 IncFsErrorCode IncFs_WaitForPageReads(const IncFsControl* control, int32_t timeoutMs,
254                                       IncFsReadInfo buffer[], size_t* bufferSize);
255 
256 IncFsErrorCode IncFs_WaitForPendingReadsWithUid(const IncFsControl* control, int32_t timeoutMs,
257                                                 IncFsReadInfoWithUid buffer[], size_t* bufferSize);
258 IncFsErrorCode IncFs_WaitForPageReadsWithUid(const IncFsControl* control, int32_t timeoutMs,
259                                              IncFsReadInfoWithUid buffer[], size_t* bufferSize);
260 
261 IncFsErrorCode IncFs_WaitForFsWrittenBlocksChange(const IncFsControl* control, int32_t timeoutMs,
262                                                   IncFsSize* count);
263 
264 IncFsFd IncFs_OpenForSpecialOpsByPath(const IncFsControl* control, const char* path);
265 IncFsFd IncFs_OpenForSpecialOpsById(const IncFsControl* control, IncFsFileId id);
266 
267 IncFsErrorCode IncFs_WriteBlocks(const IncFsDataBlock blocks[], size_t blocksCount);
268 
269 IncFsErrorCode IncFs_SetUidReadTimeouts(const IncFsControl* control,
270                                         const IncFsUidReadTimeouts timeouts[], size_t count);
271 IncFsErrorCode IncFs_GetUidReadTimeouts(const IncFsControl* control,
272                                         IncFsUidReadTimeouts timeoutsBuffer[], size_t* bufferSize);
273 
274 IncFsErrorCode IncFs_GetFileBlockCountByPath(const IncFsControl* control, const char* path,
275                                              IncFsBlockCounts* blockCount);
276 IncFsErrorCode IncFs_GetFileBlockCountById(const IncFsControl* control, IncFsFileId id,
277                                            IncFsBlockCounts* blockCount);
278 
279 IncFsErrorCode IncFs_ListIncompleteFiles(const IncFsControl* control, IncFsFileId ids[],
280                                          size_t* bufferSize);
281 
282 // Calls a passed callback for each file on the mounted filesystem, or, in the second case,
283 // for each incomplete file (only for v2 IncFS).
284 // Callback can stop the iteration early by returning |false|.
285 // Return codes:
286 // >=0      - number of files iterated,
287 // <0       - -errno
288 typedef bool (*FileCallback)(void* context, const IncFsControl* control, IncFsFileId fileId);
289 IncFsErrorCode IncFs_ForEachFile(const IncFsControl* control, void* context, FileCallback cb);
290 IncFsErrorCode IncFs_ForEachIncompleteFile(const IncFsControl* control, void* context,
291                                            FileCallback cb);
292 
293 IncFsErrorCode IncFs_WaitForLoadingComplete(const IncFsControl* control, int32_t timeoutMs);
294 
295 // Gets a collection of filled ranges in the file from IncFS. Uses the |outBuffer| memory, it has
296 // to be big enough to fit all the ranges the caller is expecting.
297 // Return codes:
298 //  0       - success,
299 //  -ERANGE - input buffer is too small. filledRanges are still valid up to the outBuffer.size,
300 //            but there are more,
301 //  <0      - error, |filledRanges| is not valid.
302 IncFsErrorCode IncFs_GetFilledRanges(int fd, IncFsSpan outBuffer, IncFsFilledRanges* filledRanges);
303 IncFsErrorCode IncFs_GetFilledRangesStartingFrom(int fd, int startBlockIndex, IncFsSpan outBuffer,
304                                                  IncFsFilledRanges* filledRanges);
305 // Check if the file is fully loaded. Return codes:
306 //  0        - fully loaded,
307 //  -ENODATA - some blocks are missing,
308 //  <0       - error from the syscall.
309 IncFsErrorCode IncFs_IsFullyLoaded(int fd);
310 IncFsErrorCode IncFs_IsFullyLoadedByPath(const IncFsControl* control, const char* path);
311 IncFsErrorCode IncFs_IsFullyLoadedById(const IncFsControl* control, IncFsFileId fileId);
312 
313 // Check if all files on the mount are fully loaded. Return codes:
314 //  0        - fully loaded,
315 //  -ENODATA - some blocks are missing,
316 //  <0       - error from the syscall.
317 IncFsErrorCode IncFs_IsEverythingFullyLoaded(const IncFsControl* control);
318 
319 // Reserve |size| bytes for the file. Trims reserved space to the current file size when |size = -1|
320 static const IncFsSize kIncFsTrimReservedSpace = -1;
321 IncFsErrorCode IncFs_ReserveSpaceByPath(const IncFsControl* control, const char* path,
322                                         IncFsSize size);
323 IncFsErrorCode IncFs_ReserveSpaceById(const IncFsControl* control, IncFsFileId id, IncFsSize size);
324 
325 // Gets the metrics of a mount by specifying the corresponding sysfs subpath.
326 // Return codes:
327 // =0       - success
328 // <0       - -errno
329 IncFsErrorCode IncFs_GetMetrics(const char* sysfsName, IncFsMetrics* metrics);
330 
331 // Gets information about the last read error of a mount.
332 // Return codes:
333 // =0       - success
334 // <0       - -errno
335 // When there is no read error, still returns success. Fields in IncFsLastReadError will be all 0.
336 // Possible values of IncFsLastReadError.errorNo:
337 //   -ETIME for read timeout;
338 //   -EBADMSG for hash verification failure;
339 //   Other negative values for other types of errors.
340 IncFsErrorCode IncFs_GetLastReadError(const IncFsControl* control,
341                                       IncFsLastReadError* lastReadError);
342 
343 __END_DECLS
344 
345 #endif // ANDROID_INCREMENTAL_FILE_SYSTEM_NDK_H
346