fs-api.c revision cca4ba2a504d70a9fe9fee37f8433997359de52c
a8c5a86d183db25a57bf193c06b41e092ec2e151Timo Sirainen* Copyright (c) 2010-2013 Dovecot authors, see the included COPYING file */
d41573018e85896ec836d897fd554e87126147f5Timo Sirainenfs_alloc(const struct fs *fs_class, const char *args,
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen const struct fs_settings *set, struct fs **fs_r, const char **error_r)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* a bit kludgy way to allow data stack frame usage in normal
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen conditions but still be able to return error message from
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen data stack. */
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen *error_r = t_strdup_printf("%s: %s", fs_class->name,
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainenstatic void fs_class_register(const struct fs *fs_class)
c21c33a8c98972c45349066fc76ac9e2c05013c1Timo Sirainenstatic void fs_classes_init(void)
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainenstatic const struct fs *fs_class_find(const char *driver)
b99f3f908d51f4d1f7628bdf2cc6100cd8587656Timo Sirainenstatic void fs_class_try_load_plugin(const char *driver)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const char *module_name = t_strdup_printf("fs_%s", driver);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen fs_modules = module_dir_load_missing(fs_modules, MODULE_DIR,
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen module = module_dir_find(fs_modules, module_name);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen module_get_symbol(module, t_strdup_printf("fs_class_%s", driver));
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainenint fs_init(const char *driver, const char *args,
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen *error_r = t_strdup_printf("Unknown fs driver: %s", driver);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return fs_alloc(fs_class, args, set, fs_r, error_r);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainenstruct fs_file *fs_file_init(struct fs *fs, const char *path, int mode_flags)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen file = fs->v.file_init(fs, path, mode_flags & FS_OPEN_MODE_MASK,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainenenum fs_properties fs_get_properties(struct fs *fs)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen file->metadata_pool = pool_alloconly_create("fs metadata", 1024);
b9ec0443d7d8afebfe61c17a9d692d6fad30c276Timo Sirainen p_array_init(&file->metadata, file->metadata_pool, 8);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainenvoid fs_default_set_metadata(struct fs_file *file,
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen metadata = array_append_space(&file->metadata);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen metadata->key = p_strdup(file->metadata_pool, key);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen metadata->value = p_strdup(file->metadata_pool, value);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainenvoid fs_set_metadata(struct fs_file *file, const char *key, const char *value)
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen fs_set_error(file->fs, "Metadata not supported by backend");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return file->fs->v.get_metadata(file, metadata_r);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return file->fs->v.get_path == NULL ? file->path :
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen return "BUG: Unknown fs error";
68b3667c9ee95951d7c3e03b19b2d37abbaa5736Timo Sirainenconst char *fs_file_last_error(struct fs_file *file)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenbool fs_prefetch(struct fs_file *file, uoff_t length)
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmodyssize_t fs_read_via_stream(struct fs_file *file, void *buf, size_t size)
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody const unsigned char *data;
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody file->pending_read_input = fs_read_stream(file, size+1);
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody ret = i_stream_read_data(file->pending_read_input,
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen if (ret < 0 && file->pending_read_input->stream_errno != 0) {
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmodyssize_t fs_read(struct fs_file *file, void *buf, size_t size)
4e6629cb5d5e7f67d5023eda540105d32df5f2baPhil Carmody /* backend didn't bother to implement read(), but we can do it with
aba9cc9bf97576c0ca653d4e218567e617061029Phil Carmodystruct istream *fs_read_stream(struct fs_file *file, size_t max_buffer_size)
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody return file->fs->v.read_stream(file, max_buffer_size);
4e6629cb5d5e7f67d5023eda540105d32df5f2baPhil Carmodyint fs_write_via_stream(struct fs_file *file, const void *data, size_t size)
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody if ((ret = o_stream_send(output, data, size)) < 0) {
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody fs_set_error(file->fs, "fs_write(%s) failed: %m",
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainenint fs_write(struct fs_file *file, const void *data, size_t size)
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen /* backend didn't bother to implement write(), but we can do it with
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainenstruct ostream *fs_write_stream(struct fs_file *file)
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainenint fs_write_stream_finish(struct fs_file *file, struct ostream **output)
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen return file->fs->v.write_stream_finish(file, TRUE);
1e2887ae909d9817cc43a7e40ecb50508419f7edTimo Sirainenint fs_write_stream_finish_async(struct fs_file *file)
1e2887ae909d9817cc43a7e40ecb50508419f7edTimo Sirainen return file->fs->v.write_stream_finish(file, TRUE);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainenvoid fs_write_stream_abort(struct fs_file *file, struct ostream **output)
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen (void)file->fs->v.write_stream_finish(file, FALSE);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainenvoid fs_file_set_async_callback(struct fs_file *file,
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen file->fs->v.set_async_callback(file, callback, context);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainenint fs_lock(struct fs_file *file, unsigned int secs, struct fs_lock **lock_r)
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainenint fs_stat(struct fs_file *file, struct stat *st_r)
cd5ee8630497fdbd853ef588a858b4ef619a5e03Timo Sirainenint fs_default_copy(struct fs_file *src, struct fs_file *dest)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen i_assert(src == NULL || src == dest->copy_src);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen dest->copy_input = fs_read_stream(src, IO_BLOCK_SIZE);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen while (o_stream_send_istream(dest->copy_output, dest->copy_input) > 0) ;
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen fs_set_error(dest->fs, "write(%s) failed: %m",
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen if (fs_write_stream_finish(dest, &dest->copy_output) < 0)
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainenint fs_copy(struct fs_file *src, struct fs_file *dest)
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainenint fs_rename(struct fs_file *src, struct fs_file *dest)
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainenfs_iter_init(struct fs *fs, const char *path, enum fs_iter_flags flags)
21ec6628c567eeff025af35d8027be01044b0b1aTimo Sirainenvoid fs_set_error(struct fs *fs, const char *fmt, ...)
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainenvoid fs_set_critical(struct fs *fs, const char *fmt, ...)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("fs-%s: %s", fs->name, str_c(fs->last_error));
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen fs_set_error(fs, "Asynchronous operation in progress");