1 #ifndef FS_API_H
2 #define FS_API_H
3 
4 struct stat;
5 struct fs;
6 struct fs_file;
7 struct fs_lock;
8 struct hash_method;
9 
10 /* Metadata with this prefix shouldn't actually be sent to storage. */
11 #define FS_METADATA_INTERNAL_PREFIX ":/X-Dovecot-fs-api-"
12 /* fs_write*() may return a hex-encoded object ID after write is finished.
13    This can be later on used to optimize reads by setting it before reading
14    the file. */
15 #define FS_METADATA_OBJECTID FS_METADATA_INTERNAL_PREFIX"ObjectID"
16 /* Calling this before fs_write_stream_finish() allows renaming the filename.
17    This can be useful if you don't know the final filename before writing it
18    (e.g. filename contains the file size). The given filename must include the
19    full path also. */
20 #define FS_METADATA_WRITE_FNAME FS_METADATA_INTERNAL_PREFIX"WriteFilename"
21 /* Original path of the file. The path that's eventually visible to a fs
22    backend may be something different, e.g. object ID. This allows the backend
23    to still access the original path. */
24 #define FS_METADATA_ORIG_PATH FS_METADATA_INTERNAL_PREFIX"OrigPath"
25 
26 enum fs_properties {
27 	FS_PROPERTY_METADATA	= 0x01,
28 	FS_PROPERTY_LOCKS	= 0x02,
29 	FS_PROPERTY_FASTCOPY	= 0x04,
30 	FS_PROPERTY_RENAME	= 0x08,
31 	FS_PROPERTY_STAT	= 0x10,
32 	/* Iteration is possible */
33 	FS_PROPERTY_ITER	= 0x20,
34 	/* Iteration always returns all of the files (instead of possibly
35 	   slightly out of date view) */
36 	FS_PROPERTY_RELIABLEITER= 0x40,
37 	/* Backend uses directories, which aren't automatically deleted
38 	   when its children are deleted. */
39 	FS_PROPERTY_DIRECTORIES	= 0x80,
40 	FS_PROPERTY_WRITE_HASH_MD5	= 0x100,
41 	FS_PROPERTY_WRITE_HASH_SHA256	= 0x200,
42 	/* fs_copy() will copy the metadata if fs_set_metadata() hasn't
43 	   been explicitly called. */
44 	FS_PROPERTY_COPY_METADATA	= 0x400,
45 	/* Backend support asynchronous file operations. */
46 	FS_PROPERTY_ASYNC		= 0x800,
47 	/* Backend supports FS_ITER_FLAG_OBJECTIDS. */
48 	FS_PROPERTY_OBJECTIDS		= 0x1000,
49 	/* fs_copy() is fast even when file's metadata is changed */
50 	FS_PROPERTY_FASTCOPY_CHANGED_METADATA = 0x2000,
51 };
52 
53 enum fs_open_mode {
54 	/* Open only for reading, or fail with ENOENT if it doesn't exist */
55 	FS_OPEN_MODE_READONLY,
56 	/* Create a new file, fail with EEXIST if it already exists */
57 	FS_OPEN_MODE_CREATE,
58 	/* Create a new file with a new unique name. The generated name is a
59 	   128bit hex-encoded string. The fs_open()'s path parameter specifies
60 	   only the directory where the file is created to. */
61 	FS_OPEN_MODE_CREATE_UNIQUE_128,
62 	/* Create or replace a file */
63 	FS_OPEN_MODE_REPLACE,
64 	/* Append to existing file, fail with ENOENT if it doesn't exist */
65 	FS_OPEN_MODE_APPEND
66 
67 #define FS_OPEN_MODE_MASK 0x0f
68 };
69 
70 enum fs_open_flags {
71 	/* File is important and writing must call fsync() or have equivalent
72 	   behavior. */
73 	FS_OPEN_FLAG_FSYNC		= 0x10,
74 	/* Asynchronous writes: fs_write() will fail with EAGAIN if it needs to
75 	   be called again (the retries can use size=0). For streams
76 	   fs_write_stream_finish() may request retrying with 0.
77 
78 	   Asynchronous reads: fs_read() will fail with EAGAIN if it's not
79 	   finished and fs_read_stream() returns a nonblocking stream. */
80 	FS_OPEN_FLAG_ASYNC		= 0x20,
81 	/* fs_read_stream() must return a seekable input stream */
82 	FS_OPEN_FLAG_SEEKABLE		= 0x40,
83 	/* Backend should handle this file's operations immediately without
84 	   any additional command queueing. The caller is assumed to be the one
85 	   doing any rate limiting if needed. This flag can only be used with
86 	   ASYNC flag, synchronous requests are never queued. */
87 	FS_OPEN_FLAG_ASYNC_NOQUEUE	= 0x80
88 };
89 
90 enum fs_iter_flags {
91 	/* Iterate only directories, not files */
92 	FS_ITER_FLAG_DIRS	= 0x01,
93 	/* Request asynchronous iteration. */
94 	FS_ITER_FLAG_ASYNC	= 0x02,
95 	/* Instead of returning object names, return <objectid>/<object name>.
96 	   If this isn't supported, the <objectid> is returned empty. The
97 	   object IDs are always hex-encoded data. This flag can be used only
98 	   if FS_PROPERTY_OBJECTIDS is enabled. */
99 	FS_ITER_FLAG_OBJECTIDS	= 0x04,
100 	/* Explicitly disable all caching for this iteration (if anything
101 	   happens to be enabled). This should be used only in situations where
102 	   the iteration is used to fix something that is broken, e.g. doveadm
103 	   force-resync. */
104 	FS_ITER_FLAG_NOCACHE	= 0x08
105 };
106 
107 enum fs_op {
108 	FS_OP_WAIT,
109 	FS_OP_METADATA,
110 	FS_OP_PREFETCH,
111 	FS_OP_READ,
112 	FS_OP_WRITE,
113 	FS_OP_LOCK,
114 	FS_OP_EXISTS,
115 	FS_OP_STAT,
116 	FS_OP_COPY,
117 	FS_OP_RENAME,
118 	FS_OP_DELETE,
119 	FS_OP_ITER,
120 
121 	FS_OP_COUNT
122 };
123 
124 struct fs_settings {
125 	/* Username and session ID are mainly used for debugging/logging,
126 	   but may also be useful for other purposes if they exist (they
127 	   may be NULL). */
128 	const char *username;
129 	const char *session_id;
130 
131 	/* Dovecot instance's base_dir */
132 	const char *base_dir;
133 	/* Directory where temporary files can be created at any time
134 	   (e.g. /tmp or mail_temp_dir) */
135 	const char *temp_dir;
136 	/* SSL client settings. */
137 	const struct ssl_iostream_settings *ssl_client_set;
138 
139 	/* Automatically try to rmdir() directories up to this path when
140 	   deleting files. */
141 	const char *root_path;
142 	/* When creating temporary files, use this prefix
143 	   (to avoid conflicts with existing files). */
144 	const char *temp_file_prefix;
145 	/* If the backend needs to do DNS lookups, use this dns_client for
146 	   them. */
147 	struct dns_client *dns_client;
148 
149 	/* Parent event to use, unless overridden by
150 	   fs_file_init_with_event() */
151 	struct event *event_parent;
152 
153 	/* Enable debugging */
154 	bool debug;
155 	/* Enable timing statistics */
156 	bool enable_timing;
157 };
158 
159 struct fs_stats {
160 	/* Number of fs_prefetch() calls. Counted only if fs_read*() hasn't
161 	   already been called for the file (which would be pretty pointless
162 	   to do). */
163 	unsigned int prefetch_count;
164 	/* Number of fs_read*() calls. Counted only if fs_prefetch() hasn't
165 	   already been called for the file. */
166 	unsigned int read_count;
167 	/* Number of fs_lookup_metadata() calls. Counted only if neither
168 	   fs_read*() nor fs_prefetch() has been called for the file. */
169 	unsigned int lookup_metadata_count;
170 	/* Number of fs_stat() calls. Counted only if none of the above
171 	   has been called (because the stat result should be cached). */
172 	unsigned int stat_count;
173 
174 	/* Number of fs_write*() calls. */
175 	unsigned int write_count;
176 	/* Number of fs_exists() calls, which actually went to the backend
177 	   instead of being handled by fs_stat() call due to fs_exists() not
178 	   being implemented. */
179 	unsigned int exists_count;
180 	/* Number of fs_delete() calls. */
181 	unsigned int delete_count;
182 	/* Number of fs_copy() calls. If backend doesn't implement copying
183 	   operation but falls back to regular read+write instead, this count
184 	   isn't increased but the read+write counters are. */
185 	unsigned int copy_count;
186 	/* Number of fs_rename() calls. */
187 	unsigned int rename_count;
188 	/* Number of fs_iter_init() calls. */
189 	unsigned int iter_count;
190 
191 	/* Number of bytes written by fs_write*() calls. */
192 	uint64_t write_bytes;
193 
194 	/* Cumulative sum of usecs spent on calls - set only if
195 	   fs_settings.enable_timing=TRUE */
196 	struct stats_dist *timings[FS_OP_COUNT];
197 };
198 
199 struct fs_metadata {
200 	const char *key;
201 	const char *value;
202 };
203 ARRAY_DEFINE_TYPE(fs_metadata, struct fs_metadata);
204 
205 typedef void fs_file_async_callback_t(void *context);
206 
207 int fs_init(const char *driver, const char *args,
208 	    const struct fs_settings *set,
209 	    struct fs **fs_r, const char **error_r);
210 /* helper for fs_init, accepts a filesystem string
211    that can come directly from config */
212 int fs_init_from_string(const char *str, const struct fs_settings *set,
213 			struct fs **fs_r, const char **error_r);
214 /* same as fs_unref() */
215 void fs_deinit(struct fs **fs);
216 
217 void fs_ref(struct fs *fs);
218 void fs_unref(struct fs **fs);
219 
220 /* Returns the parent filesystem (if this is a wrapper fs) or NULL if
221    there's no parent. */
222 struct fs *fs_get_parent(struct fs *fs);
223 /* Returns the filesystem's driver name. */
224 const char *fs_get_driver(struct fs *fs);
225 /* Returns the root fs's driver name (bypassing all wrapper fses) */
226 const char *fs_get_root_driver(struct fs *fs);
227 
228 struct fs_file *fs_file_init(struct fs *fs, const char *path, int mode_flags);
229 struct fs_file *fs_file_init_with_event(struct fs *fs, struct event *event,
230 					const char *path, int mode_flags);
231 void fs_file_deinit(struct fs_file **file);
232 
233 /* Change flags for a file (and its parents). */
234 void fs_file_set_flags(struct fs_file *file,
235 		       enum fs_open_flags add_flags,
236 		       enum fs_open_flags remove_flags);
237 /* If the file has an input streams open, close them. */
238 void fs_file_close(struct fs_file *file);
239 
240 /* Return properties supported by backend. */
241 enum fs_properties fs_get_properties(struct fs *fs);
242 
243 /* Add/replace metadata when saving a file. This makes sense only when the
244    file is being created/replaced. */
245 void fs_set_metadata(struct fs_file *file, const char *key, const char *value);
246 /* Return file's all metadata. */
247 int fs_get_metadata(struct fs_file *file,
248 		    const ARRAY_TYPE(fs_metadata) **metadata_r);
249 /* Wrapper to fs_get_metadata() to lookup a specific key. Returns 1 if value_r
250    is set, 0 if key wasn't found, -1 if error. */
251 int fs_lookup_metadata(struct fs_file *file, const char *key,
252 		       const char **value_r);
253 /* Try to find key from the currently set metadata (without refreshing it).
254    This is typically used e.g. after writing or copying a file to find some
255    extra metadata they may have set. It can also be used after
256    fs_get_metadata() or fs_lookup_metadata() to search within the looked up
257    metadata. */
258 const char *fs_lookup_loaded_metadata(struct fs_file *file, const char *key);
259 
260 /* Returns the path given to fs_open(). If file was opened with
261    FS_OPEN_MODE_CREATE_UNIQUE_128 and the write has already finished,
262    return the path including the generated filename. */
263 const char *fs_file_path(struct fs_file *file);
264 /* Returns the file's fs. */
265 struct fs *fs_file_fs(struct fs_file *file);
266 /* Returns the file's event. */
267 struct event *fs_file_event(struct fs_file *file);
268 
269 /* Return the error message for the last failed file operation. Each file
270    keeps track of its own errors. For failed copy/rename operations the "dest"
271    file contains the error. */
272 const char *fs_file_last_error(struct fs_file *file);
273 
274 /* Try to asynchronously prefetch file into memory. Returns TRUE if file is
275    already in memory (i.e. caller should handle this file before prefetching
276    more), FALSE if not. The length is a hint of how much the caller expects
277    to read, but it may be more or less (0=whole file). */
278 bool fs_prefetch(struct fs_file *file, uoff_t length);
279 /* Returns >0 if something was read, -1 if error (errno is set). */
280 ssize_t fs_read(struct fs_file *file, void *buf, size_t size);
281 /* Returns a stream for reading from file. Multiple streams can be opened,
282    and caller must destroy the streams before closing the file. */
283 struct istream *fs_read_stream(struct fs_file *file, size_t max_buffer_size);
284 
285 /* Returns 0 if ok, -1 if error (errno is set). Note: With CREATE/REPLACE mode
286    files you can call fs_write() only once, the file creation is finished by it.
287    CREATE can return EEXIST here, if the destination file was already created.
288    With APPEND mode each fs_write() atomically appends the given data to
289    file. */
290 int fs_write(struct fs_file *file, const void *data, size_t size);
291 
292 /* Write to file via output stream. The stream will be destroyed by
293    fs_write_stream_finish/abort. The returned ostream is already corked and
294    it doesn't need to be uncorked. */
295 struct ostream *fs_write_stream(struct fs_file *file);
296 /* Finish writing via stream, calling also o_stream_flush() on the stream and
297    handling any pending errors. The file will be created/replaced/appended only
298    after this call, same as with fs_write(). Anything written to the stream
299    won't be visible earlier. Returns 1 if ok, 0 if async write isn't finished
300    yet (retry calling fs_write_stream_finish_async()), -1 if error */
301 int fs_write_stream_finish(struct fs_file *file, struct ostream **output);
302 int fs_write_stream_finish_async(struct fs_file *file);
303 /* Abort writing via stream. Anything written to the stream is discarded.
304    o_stream_ignore_last_errors() is called on the output stream so the caller
305    doesn't need to do it. This must not be called after
306    fs_write_stream_finish(), i.e. it can't be used to abort a pending async
307    write. */
308 void fs_write_stream_abort_error(struct fs_file *file, struct ostream **output, const char *error_fmt, ...) ATTR_FORMAT(3, 4);
309 
310 /* Set a hash to the following write. The storage can then verify that the
311    input data matches the specified hash, or fail if it doesn't. Typically
312    implemented by Content-MD5 header. */
313 void fs_write_set_hash(struct fs_file *file, const struct hash_method *method,
314 		       const void *digest);
315 
316 /* Call the specified callback whenever the file can be read/written to.
317    May call the callback immediately. */
318 void fs_file_set_async_callback(struct fs_file *file,
319 				fs_file_async_callback_t *callback,
320 				void *context);
321 #define fs_file_set_async_callback(file, callback, context) \
322 	fs_file_set_async_callback(file, (fs_file_async_callback_t *)(callback), \
323 		1 ? (context) : \
324 		CALLBACK_TYPECHECK(callback, void (*)(typeof(context))))
325 /* Wait until some file can be read/written to more before returning.
326    It's an error to call this when there are no pending async operations. */
327 void fs_wait_async(struct fs *fs);
328 /* Switch the fs to the current ioloop. This can be used to do fs_wait_async()
329    among other IO work. Returns TRUE if there is actually some work that can
330    be waited on. */
331 bool fs_switch_ioloop(struct fs *fs) ATTR_NOWARN_UNUSED_RESULT;
332 
333 /* Returns 1 if file exists, 0 if not, -1 if error occurred. */
334 int fs_exists(struct fs_file *file);
335 /* Delete a file. Returns 0 if file was actually deleted by us, -1 if error. */
336 int fs_delete(struct fs_file *file);
337 
338 /* Returns 0 if ok, -1 if error occurred (e.g. errno=ENOENT).
339    All fs backends may not support all stat fields. */
340 int fs_stat(struct fs_file *file, struct stat *st_r);
341 /* Get number of links to the file. This is the same as using fs_stat()'s
342    st_nlinks field, except not all backends support returning it via fs_stat().
343    Returns 0 if ok, -1 if error occurred. */
344 int fs_get_nlinks(struct fs_file *file, nlink_t *nlinks_r);
345 /* Copy an object with possibly updated metadata. Destination parent
346    directories are created automatically. Returns 0 if ok, -1 if error
347    occurred. The "dest" file contains the error. */
348 int fs_copy(struct fs_file *src, struct fs_file *dest);
349 /* Try to finish asynchronous fs_copy(). Returns the same as fs_copy(). */
350 int fs_copy_finish_async(struct fs_file *dest);
351 /* Atomically rename a file. Destination parent directories are created
352    automatically. Returns 0 if ok, -1 if error occurred. The "dest" file
353    contains the error. */
354 int fs_rename(struct fs_file *src, struct fs_file *dest);
355 
356 /* Exclusively lock a file. If file is already locked, wait for it for given
357    number of seconds (0 = fail immediately). Returns 1 if locked, 0 if wait
358    timed out, -1 if error. */
359 int fs_lock(struct fs_file *file, unsigned int secs, struct fs_lock **lock_r);
360 void fs_unlock(struct fs_lock **lock);
361 
362 /* Iterate through all files or directories in the given directory.
363    Doesn't recurse to child directories. It's not an error to iterate a
364    nonexistent directory. */
365 struct fs_iter *
366 fs_iter_init(struct fs *fs, const char *path, enum fs_iter_flags flags);
367 struct fs_iter *
368 fs_iter_init_with_event(struct fs *fs, struct event *event,
369 			const char *path, enum fs_iter_flags flags);
370 /* Returns 0 if ok, -1 if iteration failed. */
371 int fs_iter_deinit(struct fs_iter **iter, const char **error_r);
372 /* Returns the next filename. */
373 const char *fs_iter_next(struct fs_iter *iter);
374 
375 /* For asynchronous iterations: Specify the callback that is called whenever
376    there's more data available for reading. */
377 void fs_iter_set_async_callback(struct fs_iter *iter,
378 				fs_file_async_callback_t *callback,
379 				void *context);
380 #define fs_iter_set_async_callback(iter, callback, context) \
381 	fs_iter_set_async_callback(iter, (fs_file_async_callback_t *)(callback), \
382 		1 ? (context) : \
383 		CALLBACK_TYPECHECK(callback, void (*)(typeof(context))))
384 /* For asynchronous iterations: If fs_iter_next() returns NULL, use this
385    function to determine if you should wait for more data or finish up. */
386 bool fs_iter_have_more(struct fs_iter *iter);
387 
388 /* Return the filesystem's fs_stats. Note that each wrapper filesystem keeps
389    track of its own fs_stats calls. You can use fs_get_parent() to get to the
390    filesystem whose stats you want to see. */
391 const struct fs_stats *fs_get_stats(struct fs *fs);
392 
393 /* Helper functions to count number of usecs for read/write operations. */
394 uint64_t fs_stats_get_read_usecs(const struct fs_stats *stats);
395 uint64_t fs_stats_get_write_usecs(const struct fs_stats *stats);
396 
397 #endif
398