1 /***********************************************************************************************************************************
2 Storage Interface
3 ***********************************************************************************************************************************/
4 #ifndef STORAGE_STORAGE_H
5 #define STORAGE_STORAGE_H
6 
7 #include <sys/types.h>
8 
9 /***********************************************************************************************************************************
10 Object type
11 ***********************************************************************************************************************************/
12 typedef struct Storage Storage;
13 
14 #include "common/type/buffer.h"
15 #include "common/type/stringList.h"
16 #include "common/io/filter/group.h"
17 #include "common/time.h"
18 #include "common/type/param.h"
19 #include "storage/info.h"
20 #include "storage/read.h"
21 #include "storage/storage.intern.h"
22 #include "storage/write.h"
23 
24 /***********************************************************************************************************************************
25 Storage feature
26 ***********************************************************************************************************************************/
27 typedef enum
28 {
29     // Does the storage support paths/directories as something that needs to be created and deleted?  Object stores (e.g. S3) often
30     // do not have paths/directories -- they are only inferred by the object name.  Therefore it doesn't make sense to create or
31     // remove directories since this implies something is happening on the storage and in the case of objects stores it would be a
32     // noop.  We'll error on any path operation (e.g. pathExists(), pathCreate(), non-recursive removes, error on missing paths,
33     // etc.) for storage that does not support paths.
34     storageFeaturePath,
35 
36     // Do paths need to be synced to ensure contents are durable?  storeageFeaturePath must also be enabled.
37     storageFeaturePathSync,
38 
39     // Is the storage able to do compression and therefore store the file more efficiently than what was written?  If so, the size
40     // will need to checked after write to see if it is different.
41     storageFeatureCompress,
42 
43     // Does the storage support hardlinks?  Hardlinks allow the same file to be linked into multiple paths to save space.
44     storageFeatureHardLink,
45 
46     // Can the storage limit the amount of data read from a file?
47     storageFeatureLimitRead,
48 
49     // Does the storage support symlinks?  Symlinks allow paths/files/links to be accessed from another path.
50     storageFeatureSymLink,
51 
52     // Does the storage support detailed info, i.e. user, group, mode, link destination, etc.
53     storageFeatureInfoDetail,
54 } StorageFeature;
55 
56 /***********************************************************************************************************************************
57 Functions
58 ***********************************************************************************************************************************/
59 // Copy a file
60 #define storageCopyP(source, destination)                                                                                          \
61     storageCopy(source, destination)
62 
63 bool storageCopy(StorageRead *source, StorageWrite *destination);
64 
65 // Does a file exist? This function is only for files, not paths.
66 typedef struct StorageExistsParam
67 {
68     VAR_PARAM_HEADER;
69     TimeMSec timeout;
70 } StorageExistsParam;
71 
72 #define storageExistsP(this, pathExp, ...)                                                                                         \
73     storageExists(this, pathExp, (StorageExistsParam){VAR_PARAM_INIT, __VA_ARGS__})
74 
75 bool storageExists(const Storage *this, const String *pathExp, StorageExistsParam param);
76 
77 // Read from storage into a buffer
78 typedef struct StorageGetParam
79 {
80     VAR_PARAM_HEADER;
81     size_t exactSize;
82 } StorageGetParam;
83 
84 #define storageGetP(file, ...)                                                                                                     \
85     storageGet(file, (StorageGetParam){VAR_PARAM_INIT, __VA_ARGS__})
86 
87 Buffer *storageGet(StorageRead *file, StorageGetParam param);
88 
89 // File/path info
90 typedef struct StorageInfoParam
91 {
92     VAR_PARAM_HEADER;
93     StorageInfoLevel level;
94     bool ignoreMissing;
95     bool followLink;
96     bool noPathEnforce;
97 } StorageInfoParam;
98 
99 #define storageInfoP(this, fileExp, ...)                                                                                           \
100     storageInfo(this, fileExp, (StorageInfoParam){VAR_PARAM_INIT, __VA_ARGS__})
101 
102 StorageInfo storageInfo(const Storage *this, const String *fileExp, StorageInfoParam param);
103 
104 // Info for all files/paths in a path
105 typedef void (*StorageInfoListCallback)(void *callbackData, const StorageInfo *info);
106 
107 typedef struct StorageInfoListParam
108 {
109     VAR_PARAM_HEADER;
110     StorageInfoLevel level;
111     bool errorOnMissing;
112     bool recurse;
113     SortOrder sortOrder;
114     const String *expression;
115 } StorageInfoListParam;
116 
117 #define storageInfoListP(this, fileExp, callback, callbackData, ...)                                                               \
118     storageInfoList(this, fileExp, callback, callbackData, (StorageInfoListParam){VAR_PARAM_INIT, __VA_ARGS__})
119 
120 bool storageInfoList(
121     const Storage *this, const String *pathExp, StorageInfoListCallback callback, void *callbackData, StorageInfoListParam param);
122 
123 // Get a list of files from a directory
124 typedef struct StorageListParam
125 {
126     VAR_PARAM_HEADER;
127     bool errorOnMissing;
128     bool nullOnMissing;
129     const String *expression;
130 } StorageListParam;
131 
132 #define storageListP(this, pathExp, ...)                                                                                           \
133     storageList(this, pathExp, (StorageListParam){VAR_PARAM_INIT, __VA_ARGS__})
134 
135 StringList *storageList(const Storage *this, const String *pathExp, StorageListParam param);
136 
137 // Move a file
138 #define storageMoveP(this, source, destination)                                                                                    \
139     storageMove(this, source, destination)
140 
141 void storageMove(const Storage *this, StorageRead *source, StorageWrite *destination);
142 
143 // Open a file for reading
144 typedef struct StorageNewReadParam
145 {
146     VAR_PARAM_HEADER;
147     bool ignoreMissing;
148     bool compressible;
149 
150     // Limit bytes to read from the file (must be varTypeUInt64). NULL for no limit.
151     const Variant *limit;
152 } StorageNewReadParam;
153 
154 #define storageNewReadP(this, pathExp, ...)                                                                                        \
155     storageNewRead(this, pathExp, (StorageNewReadParam){VAR_PARAM_INIT, __VA_ARGS__})
156 
157 StorageRead *storageNewRead(const Storage *this, const String *fileExp, StorageNewReadParam param);
158 
159 // Open a file for writing
160 typedef struct StorageNewWriteParam
161 {
162     VAR_PARAM_HEADER;
163     bool noCreatePath;
164     bool noSyncFile;
165     bool noSyncPath;
166     bool noAtomic;
167     bool compressible;
168     mode_t modeFile;
169     mode_t modePath;
170     time_t timeModified;
171     const String *user;
172     const String *group;
173 } StorageNewWriteParam;
174 
175 #define storageNewWriteP(this, pathExp, ...)                                                                                       \
176     storageNewWrite(this, pathExp, (StorageNewWriteParam){VAR_PARAM_INIT, __VA_ARGS__})
177 
178 StorageWrite *storageNewWrite(const Storage *this, const String *fileExp, StorageNewWriteParam param);
179 
180 // Get absolute path in the storage
181 typedef struct StoragePathParam
182 {
183     VAR_PARAM_HEADER;
184     bool noEnforce;
185 } StoragePathParam;
186 
187 #define storagePathP(this, pathExp, ...)                                                                                                \
188     storagePath(this, pathExp, (StoragePathParam){VAR_PARAM_INIT, __VA_ARGS__})
189 
190 String *storagePath(const Storage *this, const String *pathExp, StoragePathParam param);
191 
192 // Create a path
193 typedef struct StoragePathCreateParam
194 {
195     VAR_PARAM_HEADER;
196     bool errorOnExists;
197     bool noParentCreate;
198     mode_t mode;
199 } StoragePathCreateParam;
200 
201 #define storagePathCreateP(this, pathExp, ...)                                                                                     \
202     storagePathCreate(this, pathExp, (StoragePathCreateParam){VAR_PARAM_INIT, __VA_ARGS__})
203 
204 void storagePathCreate(const Storage *this, const String *pathExp, StoragePathCreateParam param);
205 
206 // Does a path exist?
207 #define storagePathExistsP(this, pathExp)                                                                                          \
208     storagePathExists(this, pathExp)
209 
210 bool storagePathExists(const Storage *this, const String *pathExp);
211 
212 // Remove a path
213 typedef struct StoragePathRemoveParam
214 {
215     VAR_PARAM_HEADER;
216     bool errorOnMissing;
217     bool recurse;
218 } StoragePathRemoveParam;
219 
220 #define storagePathRemoveP(this, pathExp, ...)                                                                                     \
221     storagePathRemove(this, pathExp, (StoragePathRemoveParam){VAR_PARAM_INIT, __VA_ARGS__})
222 
223 void storagePathRemove(const Storage *this, const String *pathExp, StoragePathRemoveParam param);
224 
225 // Sync a path
226 #define storagePathSyncP(this, pathExp)                                                                                            \
227     storagePathSync(this, pathExp)
228 
229 void storagePathSync(const Storage *this, const String *pathExp);
230 
231 // Write a buffer to storage
232 #define storagePutP(file, buffer)                                                                                                  \
233     storagePut(file, buffer)
234 
235 void storagePut(StorageWrite *file, const Buffer *buffer);
236 
237 // Remove a file
238 typedef struct StorageRemoveParam
239 {
240     VAR_PARAM_HEADER;
241     bool errorOnMissing;
242 } StorageRemoveParam;
243 
244 #define storageRemoveP(this, fileExp, ...)                                                                                         \
245     storageRemove(this, fileExp, (StorageRemoveParam){VAR_PARAM_INIT, __VA_ARGS__})
246 
247 void storageRemove(const Storage *this, const String *fileExp, StorageRemoveParam param);
248 
249 /***********************************************************************************************************************************
250 Getters/Setters
251 ***********************************************************************************************************************************/
252 // Is the feature supported by this storage?
253 __attribute__((always_inline)) static inline bool
storageFeature(const Storage * const this,const StorageFeature feature)254 storageFeature(const Storage *const this, const StorageFeature feature)
255 {
256     return THIS_PUB(Storage)->interface.feature >> feature & 1;
257 }
258 
259 // Storage type (posix, cifs, etc.)
260 __attribute__((always_inline)) static inline StringId
storageType(const Storage * const this)261 storageType(const Storage *const this)
262 {
263     return THIS_PUB(Storage)->type;
264 }
265 
266 /***********************************************************************************************************************************
267 Macros for function logging
268 ***********************************************************************************************************************************/
269 String *storageToLog(const Storage *this);
270 
271 #define FUNCTION_LOG_STORAGE_TYPE                                                                                                  \
272     Storage *
273 #define FUNCTION_LOG_STORAGE_FORMAT(value, buffer, bufferSize)                                                                     \
274     FUNCTION_LOG_STRING_OBJECT_FORMAT(value, storageToLog, buffer, bufferSize)
275 
276 #endif
277