fs-api.h revision 42d2fdfbe4047c0aab78c76a10f31766aa53ecd7
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch#ifndef FS_API_H
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#define FS_API_H
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstruct stat;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainenstruct fs;
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainenstruct fs_file;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstruct fs_lock;
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen
b13f738e8eb3f24dc2abf2c804f954b4d864ac6fTimo Sirainenenum fs_properties {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen FS_PROPERTY_METADATA = 0x01,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen FS_PROPERTY_LOCKS = 0x02,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen FS_PROPERTY_FASTCOPY = 0x04,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen FS_PROPERTY_RENAME = 0x08,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen FS_PROPERTY_STAT = 0x10,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* Iteration is possible */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen FS_PROPERTY_ITER = 0x20,
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen /* Iteration always returns all of the files (instead of possibly
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen slightly out of date view) */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen FS_PROPERTY_RELIABLEITER= 0x40,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* Backend uses directories, which aren't automatically deleted
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen when its children are deleted. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen FS_PROPERTY_DIRECTORIES = 0x80
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen};
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenenum fs_open_mode {
4c1deab456fe8877bf025d11843167ac1f36327aTimo Sirainen /* Open only for reading, or fail with ENOENT if it doesn't exist */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen FS_OPEN_MODE_READONLY,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* Create a new file, fail with EEXIST if it already exists */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen FS_OPEN_MODE_CREATE,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* Create a new file with a new unique name. The generated name is a
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen 128bit hex-encoded string. The fs_open()'s path parameter specifies
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen only the directory where the file is created to. */
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen FS_OPEN_MODE_CREATE_UNIQUE_128,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* Create or replace a file */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen FS_OPEN_MODE_REPLACE,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* Append to existing file, fail with ENOENT if it doesn't exist */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen FS_OPEN_MODE_APPEND
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen#define FS_OPEN_MODE_MASK 0x0f
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen};
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenenum fs_open_flags {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* File is important and writing must call fsync() or have equivalent
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen behavior. */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen FS_OPEN_FLAG_FSYNC = 0x10,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* Asynchronous writes: fs_write() will fail with EAGAIN if it needs to
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen be called again (the retries can use size=0). For streams
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen fs_write_stream_finish() may request retrying with 0.
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen Asynchronous reads: fs_read() will fail with EAGAIN if it's not
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen finished and fs_read_stream() returns a nonblocking stream. */
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen FS_OPEN_FLAG_ASYNC = 0x20,
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen /* fs_read_stream() must return a seekable input stream */
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen FS_OPEN_FLAG_SEEKABLE = 0x40
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen};
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainenenum fs_iter_flags {
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen /* Iterate only directories, not files */
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen FS_ITER_FLAG_DIRS = 0x01
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen};
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainenstruct fs_settings {
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen /* Dovecot instance's base_dir */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *base_dir;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen /* Directory where temporary files can be created at any time
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (e.g. /tmp or mail_temp_dir) */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *temp_dir;
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* Automatically try to rmdir() directories up to this path when
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen deleting files. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *root_path;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen /* When creating temporary files, use this prefix
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (to avoid conflicts with existing files). */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *temp_file_prefix;
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen};
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainenstruct fs_metadata {
ad396be1d926e49cd31b0732824362647ecd5fc2Timo Sirainen const char *key;
ad396be1d926e49cd31b0732824362647ecd5fc2Timo Sirainen const char *value;
ad396be1d926e49cd31b0732824362647ecd5fc2Timo Sirainen};
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo SirainenARRAY_DEFINE_TYPE(fs_metadata, struct fs_metadata);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainentypedef void fs_file_async_callback_t(void *context);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
3c493c276f599d9b9cd10764876d648003046954Timo Sirainenint fs_init(const char *driver, const char *args,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const struct fs_settings *set,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct fs **fs_r, const char **error_r);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainenvoid fs_deinit(struct fs **fs);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainenstruct fs_file *fs_file_init(struct fs *fs, const char *path, int mode_flags);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainenvoid fs_file_deinit(struct fs_file **file);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen/* Return properties supported by backend. */
3c493c276f599d9b9cd10764876d648003046954Timo Sirainenenum fs_properties fs_get_properties(struct fs *fs);
72ba6a8227bfdf02282d7e4f4c49194af5c354ddTimo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen/* Add/replace metadata when saving a file. This makes sense only when the
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen file is being created/replaced. */
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainenvoid fs_set_metadata(struct fs_file *file, const char *key, const char *value);
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen/* Return file's all metadata. */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainenint fs_get_metadata(struct fs_file *file,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen const ARRAY_TYPE(fs_metadata) **metadata_r);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen/* Returns the path given to fs_open(). If file was opened with
72ba6a8227bfdf02282d7e4f4c49194af5c354ddTimo Sirainen FS_OPEN_MODE_CREATE_UNIQUE_128 and the write has already finished,
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen return the path including the generated filename. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenconst char *fs_file_path(struct fs_file *file);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen/* Return the error message for the last failed operation. */
3c493c276f599d9b9cd10764876d648003046954Timo Sirainenconst char *fs_last_error(struct fs *fs);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen/* Convenience function for the above. Errors aren't preserved across files. */
3c493c276f599d9b9cd10764876d648003046954Timo Sirainenconst char *fs_file_last_error(struct fs_file *file);
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen/* Try to asynchronously prefetch file into memory. Returns TRUE if file is
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen already in memory (i.e. caller should handle this file before prefetching
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen more), FALSE if not. The length is a hint of how much the caller expects
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen to read, but it may be more or less (0=whole file). */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainenbool fs_prefetch(struct fs_file *file, uoff_t length);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen/* Returns >0 if something was read, -1 if error (errno is set). */
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainenssize_t fs_read(struct fs_file *file, void *buf, size_t size);
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen/* Returns a stream for reading from file. Multiple streams can be opened,
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen and caller must destroy the streams before closing the file. */
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainenstruct istream *fs_read_stream(struct fs_file *file, size_t max_buffer_size);
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen/* Returns 0 if ok, -1 if error (errno is set). Note: With CREATE/REPLACE mode
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen files you can call fs_write() only once, the file creation is finished by it.
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen CREATE can return EEXIST here, if the destination file was already created.
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen With APPEND mode each fs_write() atomically appends the given data to
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen file. */
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainenint fs_write(struct fs_file *file, const void *data, size_t size);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen/* Write to file via output stream. The stream will be destroyed by
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen fs_write_stream_finish/abort. */
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainenstruct ostream *fs_write_stream(struct fs_file *file);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen/* Finish writing via stream. The file will be created/replaced/appended only
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen after this call, same as with fs_write(). Anything written to the stream
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen won't be visible earlier. Returns 1 if ok, 0 if async write isn't finished
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen yet (retry calling fs_write_stream_finish_async()), -1 if error */
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainenint fs_write_stream_finish(struct fs_file *file, struct ostream **output);
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainenint fs_write_stream_finish_async(struct fs_file *file);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen/* Abort writing via stream. Anything written to the stream is discarded. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid fs_write_stream_abort(struct fs_file *file, struct ostream **output);
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen/* Call the specified callback whenever the file can be read/written to.
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen May call the callback immediately. */
3c493c276f599d9b9cd10764876d648003046954Timo Sirainenvoid fs_file_set_async_callback(struct fs_file *file,
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen fs_file_async_callback_t *callback,
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen void *context);
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen/* Wait until some file can be read/written to more before returning.
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen It's an error to call this when there are no pending async operations.
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen Returns 0 if ok, -1 if timed out. */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainenint fs_wait_async(struct fs *fs);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen/* Returns 1 if file exists, 0 if not, -1 if error occurred. */
3c493c276f599d9b9cd10764876d648003046954Timo Sirainenint fs_exists(struct fs_file *file);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen/* Delete a file. Returns 0 if file was actually deleted by us, -1 if error. */
7fa561fecd106f0e3f58315db2402f7ba83c4226Timo Sirainenint fs_delete(struct fs_file *file);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen/* Returns 0 if ok, -1 if error occurred (e.g. errno=ENOENT).
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen All fs backends may not support all stat fields. */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainenint fs_stat(struct fs_file *file, struct stat *st_r);
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen/* Copy an object with possibly updated metadata. Destination parent
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen directories are created automatically. Returns 0 if ok, -1 if error
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen occurred. */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainenint fs_copy(struct fs_file *src, struct fs_file *dest);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen/* Try to finish asynchronous fs_copy(). Returns the same as fs_copy(). */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainenint fs_copy_finish_async(struct fs_file *dest);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen/* Atomically rename a file. Destination parent directories are created
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen automatically. Returns 0 if ok, -1 if error occurred. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenint fs_rename(struct fs_file *src, struct fs_file *dest);
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen/* Exclusively lock a file. If file is already locked, wait for it for given
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen number of seconds (0 = fail immediately). Returns 1 if locked, 0 if wait
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen timed out, -1 if error. */
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainenint fs_lock(struct fs_file *file, unsigned int secs, struct fs_lock **lock_r);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid fs_unlock(struct fs_lock **lock);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen/* Iterate through all files or directories in the given directory.
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen Doesn't recurse to child directories. It's not an error to iterate a
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen nonexistent directory. */
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainenstruct fs_iter *
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainenfs_iter_init(struct fs *fs, const char *path, enum fs_iter_flags flags);
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen/* Returns 0 if ok, -1 if iteration failed. */
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainenint fs_iter_deinit(struct fs_iter **iter);
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen/* Returns the next filename. */
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainenconst char *fs_iter_next(struct fs_iter *iter);
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen#endif
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen