fs-api.h revision 4f825be38fed479bbe54ca0a76b7d1256e70ce80
#ifndef FS_API_H
#define FS_API_H
struct stat;
struct fs;
struct fs_file;
struct fs_lock;
struct hash_method;
enum fs_properties {
FS_PROPERTY_METADATA = 0x01,
FS_PROPERTY_LOCKS = 0x02,
FS_PROPERTY_FASTCOPY = 0x04,
FS_PROPERTY_RENAME = 0x08,
FS_PROPERTY_STAT = 0x10,
/* Iteration is possible */
FS_PROPERTY_ITER = 0x20,
/* Iteration always returns all of the files (instead of possibly
slightly out of date view) */
FS_PROPERTY_RELIABLEITER= 0x40,
/* Backend uses directories, which aren't automatically deleted
when its children are deleted. */
FS_PROPERTY_DIRECTORIES = 0x80,
FS_PROPERTY_WRITE_HASH_MD5 = 0x100,
FS_PROPERTY_WRITE_HASH_SHA256 = 0x200
};
enum fs_open_mode {
/* Open only for reading, or fail with ENOENT if it doesn't exist */
/* Create a new file, fail with EEXIST if it already exists */
/* Create a new file with a new unique name. The generated name is a
128bit hex-encoded string. The fs_open()'s path parameter specifies
only the directory where the file is created to. */
/* Create or replace a file */
/* Append to existing file, fail with ENOENT if it doesn't exist */
#define FS_OPEN_MODE_MASK 0x0f
};
enum fs_open_flags {
/* File is important and writing must call fsync() or have equivalent
behavior. */
FS_OPEN_FLAG_FSYNC = 0x10,
/* Asynchronous writes: fs_write() will fail with EAGAIN if it needs to
be called again (the retries can use size=0). For streams
fs_write_stream_finish() may request retrying with 0.
Asynchronous reads: fs_read() will fail with EAGAIN if it's not
finished and fs_read_stream() returns a nonblocking stream. */
FS_OPEN_FLAG_ASYNC = 0x20,
/* fs_read_stream() must return a seekable input stream */
FS_OPEN_FLAG_SEEKABLE = 0x40,
/* Backend should handle this file's operations immediately without
any additional command queueing. The caller is assumed to be the one
doing any rate limiting if needed. This flag can only be used with
ASYNC flag, synchronous requests are never queued. */
FS_OPEN_FLAG_ASYNC_NOQUEUE = 0x80
};
enum fs_iter_flags {
/* Iterate only directories, not files */
FS_ITER_FLAG_DIRS = 0x01,
/* Request asynchronous iteration. */
FS_ITER_FLAG_ASYNC = 0x02
};
struct fs_settings {
/* Dovecot instance's base_dir */
const char *base_dir;
/* Directory where temporary files can be created at any time
(e.g. /tmp or mail_temp_dir) */
const char *temp_dir;
/* SSL client settings. */
const struct ssl_iostream_settings *ssl_client_set;
/* Automatically try to rmdir() directories up to this path when
deleting files. */
const char *root_path;
/* When creating temporary files, use this prefix
(to avoid conflicts with existing files). */
const char *temp_file_prefix;
/* If the backend needs to do DNS lookups, use this dns_client for
them. */
struct dns_client *dns_client;
/* Enable debugging */
bool debug;
};
struct fs_metadata {
const char *key;
const char *value;
};
typedef void fs_file_async_callback_t(void *context);
const struct fs_settings *set,
/* Returns the root fs's driver name (bypassing all wrapper fses) */
/* If the file has an input streams open, close them. */
/* Return properties supported by backend. */
/* Return file's all metadata. */
/* Returns the path given to fs_open(). If file was opened with
FS_OPEN_MODE_CREATE_UNIQUE_128 and the write has already finished,
return the path including the generated filename. */
/* Returns the file's fs. */
/* Return the error message for the last failed operation. */
/* Convenience function for the above. Errors aren't preserved across files. */
/* Try to asynchronously prefetch file into memory. Returns TRUE if file is
already in memory (i.e. caller should handle this file before prefetching
more), FALSE if not. The length is a hint of how much the caller expects
to read, but it may be more or less (0=whole file). */
/* Returns >0 if something was read, -1 if error (errno is set). */
/* Returns a stream for reading from file. Multiple streams can be opened,
and caller must destroy the streams before closing the file. */
files you can call fs_write() only once, the file creation is finished by it.
CREATE can return EEXIST here, if the destination file was already created.
With APPEND mode each fs_write() atomically appends the given data to
file. */
/* Write to file via output stream. The stream will be destroyed by
after this call, same as with fs_write(). Anything written to the stream
won't be visible earlier. Returns 1 if ok, 0 if async write isn't finished
yet (retry calling fs_write_stream_finish_async()), -1 if error */
/* Abort writing via stream. Anything written to the stream is discarded. */
/* Set a hash to the following write. The storage can then verify that the
input data matches the specified hash, or fail if it doesn't. Typically
implemented by Content-MD5 header. */
const void *digest);
May call the callback immediately. */
void *context);
It's an error to call this when there are no pending async operations.
Returns 0 if ok, -1 if timed out. */
/* Returns 1 if file exists, 0 if not, -1 if error occurred. */
/* Delete a file. Returns 0 if file was actually deleted by us, -1 if error. */
/* Returns 0 if ok, -1 if error occurred (e.g. errno=ENOENT).
All fs backends may not support all stat fields. */
/* Copy an object with possibly updated metadata. Destination parent
directories are created automatically. Returns 0 if ok, -1 if error
occurred. */
/* Try to finish asynchronous fs_copy(). Returns the same as fs_copy(). */
/* Atomically rename a file. Destination parent directories are created
automatically. Returns 0 if ok, -1 if error occurred. */
/* Exclusively lock a file. If file is already locked, wait for it for given
number of seconds (0 = fail immediately). Returns 1 if locked, 0 if wait
timed out, -1 if error. */
/* Iterate through all files or directories in the given directory.
Doesn't recurse to child directories. It's not an error to iterate a
nonexistent directory. */
struct fs_iter *
/* Returns 0 if ok, -1 if iteration failed. */
/* Returns the next filename. */
/* For asynchronous iterations: Specify the callback that is called whenever
there's more data available for reading. */
void *context);
/* For asynchronous iterations: If fs_iter_next() returns NULL, use this
function to determine if you should wait for more data or finish up. */
#endif