fs-api.c revision cca4ba2a504d70a9fe9fee37f8433997359de52c
a8c5a86d183db25a57bf193c06b41e092ec2e151Timo Sirainen* Copyright (c) 2010-2013 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen#include "array.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "module-dir.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "str.h"
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen#include "istream.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "ostream.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "fs-api-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
463e82bdf0e990f4f2252d2b53ea23a5abe5883cTimo Sirainenstatic struct module *fs_modules = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic ARRAY(const struct fs *) fs_classes;
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen
d41573018e85896ec836d897fd554e87126147f5Timo Sirainenstatic int
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)
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen{
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen struct fs *fs;
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen int ret;
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen fs = fs_class->v.alloc();
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen fs->last_error = str_new(default_pool, 64);
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen T_BEGIN {
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen ret = fs_class->v.init(fs, args, set);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen } T_END;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (ret < 0) {
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 Sirainen fs_last_error(fs));
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen fs_deinit(&fs);
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen return -1;
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen }
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen *fs_r = fs;
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen return 0;
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen}
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainenstatic void fs_class_register(const struct fs *fs_class)
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen{
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen array_append(&fs_classes, &fs_class, 1);
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen}
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
c21c33a8c98972c45349066fc76ac9e2c05013c1Timo Sirainenstatic void fs_classes_init(void)
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen{
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen i_array_init(&fs_classes, 8);
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen fs_class_register(&fs_class_posix);
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen fs_class_register(&fs_class_metawrap);
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen fs_class_register(&fs_class_sis);
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen fs_class_register(&fs_class_sis_queue);
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen}
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainenstatic const struct fs *fs_class_find(const char *driver)
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const struct fs *const *classp;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (!array_is_created(&fs_classes))
e6d7d19c328e7043ad35d5a52c1617bde915a16fTimo Sirainen fs_classes_init();
d7095f3a4466fbb78b2d5eb3d322bc15a5b0ab1fTimo Sirainen
153de7823e64c67678b3fc95719c41a8ec5b864dTimo Sirainen array_foreach(&fs_classes, classp) {
153de7823e64c67678b3fc95719c41a8ec5b864dTimo Sirainen if (strcmp((*classp)->name, driver) == 0)
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen return *classp;
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return NULL;
e6d7d19c328e7043ad35d5a52c1617bde915a16fTimo Sirainen}
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainenstatic void fs_class_deinit_modules(void)
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen{
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen module_dir_unload(&fs_modules);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
538c58fc95200fcc5e91abdda8b912b574a2f968Timo Sirainen
b99f3f908d51f4d1f7628bdf2cc6100cd8587656Timo Sirainenstatic void fs_class_try_load_plugin(const char *driver)
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const char *module_name = t_strdup_printf("fs_%s", driver);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct module *module;
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen struct module_dir_load_settings mod_set;
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen const struct fs *fs_class;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen memset(&mod_set, 0, sizeof(mod_set));
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mod_set.abi_version = DOVECOT_ABI_VERSION;
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen mod_set.ignore_missing = TRUE;
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen fs_modules = module_dir_load_missing(fs_modules, MODULE_DIR,
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen module_name, &mod_set);
b99f3f908d51f4d1f7628bdf2cc6100cd8587656Timo Sirainen module_dir_init(fs_modules);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen module = module_dir_find(fs_modules, module_name);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen fs_class = module == NULL ? NULL :
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen module_get_symbol(module, t_strdup_printf("fs_class_%s", driver));
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (fs_class != NULL)
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen fs_class_register(fs_class);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen lib_atexit(fs_class_deinit_modules);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainenint fs_init(const char *driver, const char *args,
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen const struct fs_settings *set,
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen struct fs **fs_r, const char **error_r)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen{
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen const struct fs *fs_class;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fs_class = fs_class_find(driver);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (fs_class == NULL) {
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen T_BEGIN {
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen fs_class_try_load_plugin(driver);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen } T_END;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen fs_class = fs_class_find(driver);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (fs_class == NULL) {
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen *error_r = t_strdup_printf("Unknown fs driver: %s", driver);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return -1;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen }
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return fs_alloc(fs_class, args, set, fs_r, error_r);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen}
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainenvoid fs_deinit(struct fs **_fs)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen{
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen struct fs *fs = *_fs;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen string_t *last_error = fs->last_error;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *_fs = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (fs->files_open_count > 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_panic("fs-%s: %u files still open",
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen fs->name, fs->files_open_count);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen }
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen fs->v.deinit(fs);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen str_free(&last_error);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen}
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainenstruct fs_file *fs_file_init(struct fs *fs, const char *path, int mode_flags)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen{
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen struct fs_file *file;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen i_assert(path != NULL);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen T_BEGIN {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen file = fs->v.file_init(fs, path, mode_flags & FS_OPEN_MODE_MASK,
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen mode_flags & ~FS_OPEN_MODE_MASK);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } T_END;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fs->files_open_count++;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen return file;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen}
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainenvoid fs_file_deinit(struct fs_file **_file)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen{
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen struct fs_file *file = *_file;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen pool_t metadata_pool = file->metadata_pool;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen i_assert(file->fs->files_open_count > 0);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen *_file = NULL;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen file->fs->files_open_count--;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen file->fs->v.file_deinit(file);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (metadata_pool != NULL)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen pool_unref(&metadata_pool);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen}
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainenenum fs_properties fs_get_properties(struct fs *fs)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return fs->v.get_properties(fs);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen
b9ec0443d7d8afebfe61c17a9d692d6fad30c276Timo Sirainenvoid fs_metadata_init(struct fs_file *file)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (file->metadata_pool == NULL) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen file->metadata_pool = pool_alloconly_create("fs metadata", 1024);
b9ec0443d7d8afebfe61c17a9d692d6fad30c276Timo Sirainen p_array_init(&file->metadata, file->metadata_pool, 8);
23079bf0a6e7489c5f542b0b897a71bdfd884a51Timo Sirainen }
23079bf0a6e7489c5f542b0b897a71bdfd884a51Timo Sirainen}
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainenvoid fs_default_set_metadata(struct fs_file *file,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen const char *key, const char *value)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen{
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen struct fs_metadata *metadata;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen fs_metadata_init(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);
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainenvoid fs_set_metadata(struct fs_file *file, const char *key, const char *value)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen{
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (file->fs->v.set_metadata != NULL)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen file->fs->v.set_metadata(file, key, value);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen}
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainenint fs_get_metadata(struct fs_file *file,
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen const ARRAY_TYPE(fs_metadata) **metadata_r)
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen{
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen if (file->fs->v.get_metadata == NULL) {
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen fs_set_error(file->fs, "Metadata not supported by backend");
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return file->fs->v.get_metadata(file, metadata_r);
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenconst char *fs_file_path(struct fs_file *file)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return file->fs->v.get_path == NULL ? file->path :
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen file->fs->v.get_path(file);
68b3667c9ee95951d7c3e03b19b2d37abbaa5736Timo Sirainen}
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainenconst char *fs_last_error(struct fs *fs)
68b3667c9ee95951d7c3e03b19b2d37abbaa5736Timo Sirainen{
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody if (str_len(fs->last_error) == 0)
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen return "BUG: Unknown fs error";
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen return str_c(fs->last_error);
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen}
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen
68b3667c9ee95951d7c3e03b19b2d37abbaa5736Timo Sirainenconst char *fs_file_last_error(struct fs_file *file)
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen{
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen return fs_last_error(file->fs);
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenbool fs_prefetch(struct fs_file *file, uoff_t length)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody return file->fs->v.prefetch(file, length);
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody}
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmodyssize_t fs_read_via_stream(struct fs_file *file, void *buf, size_t size)
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody{
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody const unsigned char *data;
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody size_t data_size;
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody ssize_t ret;
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody i_assert(size > 0);
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody if (file->pending_read_input == NULL)
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody file->pending_read_input = fs_read_stream(file, size+1);
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody ret = i_stream_read_data(file->pending_read_input,
b32de04eb77234b25e2e411884a2503a1bf3c255Phil Carmody &data, &data_size, size-1);
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen if (ret == 0) {
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen fs_set_error_async(file->fs);
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen return -1;
070df93a3014ad4b2eb8754af65128c9f9a72e4ePhil Carmody }
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen if (ret < 0 && file->pending_read_input->stream_errno != 0) {
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen fs_set_error(file->fs, "read(%s) failed: %m",
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody i_stream_get_name(file->pending_read_input));
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen } else {
070df93a3014ad4b2eb8754af65128c9f9a72e4ePhil Carmody ret = I_MIN(size, data_size);
070df93a3014ad4b2eb8754af65128c9f9a72e4ePhil Carmody memcpy(buf, data, ret);
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody }
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen i_stream_unref(&file->pending_read_input);
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody return ret;
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody}
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmodyssize_t fs_read(struct fs_file *file, void *buf, size_t size)
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody{
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody if (file->fs->v.read != NULL)
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody return file->fs->v.read(file, buf, size);
74896b89e1d82819d710f9322cf7c9e72d5841adPhil Carmody
4e6629cb5d5e7f67d5023eda540105d32df5f2baPhil Carmody /* backend didn't bother to implement read(), but we can do it with
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody streams. */
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody return fs_read_via_stream(file, buf, size);
aba9cc9bf97576c0ca653d4e218567e617061029Phil Carmody}
aba9cc9bf97576c0ca653d4e218567e617061029Phil Carmody
aba9cc9bf97576c0ca653d4e218567e617061029Phil Carmodystruct istream *fs_read_stream(struct fs_file *file, size_t max_buffer_size)
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody{
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody return file->fs->v.read_stream(file, max_buffer_size);
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody}
4e6629cb5d5e7f67d5023eda540105d32df5f2baPhil Carmody
4e6629cb5d5e7f67d5023eda540105d32df5f2baPhil Carmodyint fs_write_via_stream(struct fs_file *file, const void *data, size_t size)
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody{
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody struct ostream *output;
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody ssize_t ret;
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody int err;
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody if (!file->write_pending) {
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody output = fs_write_stream(file);
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody if ((ret = o_stream_send(output, data, size)) < 0) {
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody err = errno;
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody fs_set_error(file->fs, "fs_write(%s) failed: %m",
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody o_stream_get_name(output));
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody fs_write_stream_abort(file, &output);
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody errno = err;
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody return -1;
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody }
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody i_assert((size_t)ret == size);
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody ret = fs_write_stream_finish(file, &output);
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody } else {
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody ret = fs_write_stream_finish_async(file);
4e6629cb5d5e7f67d5023eda540105d32df5f2baPhil Carmody }
89b7d6ce9266288c156e3513f5798680f1e33572Phil Carmody if (ret == 0) {
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody fs_set_error_async(file->fs);
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody file->write_pending = TRUE;
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody return -1;
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody }
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody file->write_pending = FALSE;
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody return ret < 0 ? -1 : 0;
53e0e6889bf659b86e4c7d2e83e27d69fd9d6bcbPhil Carmody}
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainen
dfdd228ab20092705da0e8812b3cd0a039319375Timo Sirainenint fs_write(struct fs_file *file, const void *data, size_t size)
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen{
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen if (file->fs->v.write != NULL)
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen return file->fs->v.write(file, data, size);
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen /* backend didn't bother to implement write(), but we can do it with
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen streams. */
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen return fs_write_via_stream(file, data, size);
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen}
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainenstruct ostream *fs_write_stream(struct fs_file *file)
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen{
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen file->fs->v.write_stream(file);
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen i_assert(file->output != NULL);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen return file->output;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen}
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainenint fs_write_stream_finish(struct fs_file *file, struct ostream **output)
1e2887ae909d9817cc43a7e40ecb50508419f7edTimo Sirainen{
1e2887ae909d9817cc43a7e40ecb50508419f7edTimo Sirainen i_assert(*output == file->output);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen *output = NULL;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen return file->fs->v.write_stream_finish(file, TRUE);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen}
1e2887ae909d9817cc43a7e40ecb50508419f7edTimo Sirainen
1e2887ae909d9817cc43a7e40ecb50508419f7edTimo Sirainenint fs_write_stream_finish_async(struct fs_file *file)
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen{
1e2887ae909d9817cc43a7e40ecb50508419f7edTimo Sirainen return file->fs->v.write_stream_finish(file, TRUE);
1e2887ae909d9817cc43a7e40ecb50508419f7edTimo Sirainen}
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainenvoid fs_write_stream_abort(struct fs_file *file, struct ostream **output)
1e2887ae909d9817cc43a7e40ecb50508419f7edTimo Sirainen{
1e2887ae909d9817cc43a7e40ecb50508419f7edTimo Sirainen i_assert(*output == file->output);
1e2887ae909d9817cc43a7e40ecb50508419f7edTimo Sirainen
1e2887ae909d9817cc43a7e40ecb50508419f7edTimo Sirainen *output = NULL;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen (void)file->fs->v.write_stream_finish(file, FALSE);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen}
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainenvoid fs_file_set_async_callback(struct fs_file *file,
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen fs_file_async_callback_t *callback,
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen void *context)
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen{
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen if (file->fs->v.set_async_callback != NULL)
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen file->fs->v.set_async_callback(file, callback, context);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen else
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen callback(context);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen}
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainenint fs_wait_async(struct fs *fs)
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen{
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen if (fs->v.wait_async == NULL)
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen return 0;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen else
4b89231f4ec9cc69f4aea715e1d34f405c7e317dTimo Sirainen return fs->v.wait_async(fs);
4b89231f4ec9cc69f4aea715e1d34f405c7e317dTimo Sirainen}
4b89231f4ec9cc69f4aea715e1d34f405c7e317dTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainenint fs_lock(struct fs_file *file, unsigned int secs, struct fs_lock **lock_r)
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen{
76959d3d6fed45d5f5e1397fcdcf09a5adb87f24Timo Sirainen return file->fs->v.lock(file, secs, lock_r);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen}
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainenvoid fs_unlock(struct fs_lock **_lock)
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen{
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen struct fs_lock *lock = *_lock;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen *_lock = NULL;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen lock->file->fs->v.unlock(lock);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen}
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainenint fs_exists(struct fs_file *file)
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen{
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen return file->fs->v.exists(file);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen}
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainenint fs_stat(struct fs_file *file, struct stat *st_r)
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen{
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen return file->fs->v.stat(file, st_r);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen}
cd5ee8630497fdbd853ef588a858b4ef619a5e03Timo Sirainen
cd5ee8630497fdbd853ef588a858b4ef619a5e03Timo Sirainenint fs_default_copy(struct fs_file *src, struct fs_file *dest)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen{
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen if (dest->copy_src != NULL) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen i_assert(src == NULL || src == dest->copy_src);
1032e5427bf10566098f3b3bb9110e2bc1227e85Timo Sirainen if (dest->copy_output == NULL) {
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen i_assert(dest->copy_input == NULL);
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen if (fs_write_stream_finish_async(dest) < 0)
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen return -1;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen dest->copy_src = NULL;
9887c39c5ba429169389153ca99de49e084a73f0Timo Sirainen return 0;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen } else {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen dest->copy_src = src;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen dest->copy_input = fs_read_stream(src, IO_BLOCK_SIZE);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen dest->copy_output = fs_write_stream(dest);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen while (o_stream_send_istream(dest->copy_output, dest->copy_input) > 0) ;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (dest->copy_input->stream_errno != 0) {
b99f3f908d51f4d1f7628bdf2cc6100cd8587656Timo Sirainen fs_set_error(dest->fs, "read(%s) failed: %m",
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_stream_get_name(dest->copy_input));
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen return -1;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen }
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen if (dest->copy_output->stream_errno != 0) {
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen fs_set_error(dest->fs, "write(%s) failed: %m",
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen o_stream_get_name(dest->copy_output));
1032e5427bf10566098f3b3bb9110e2bc1227e85Timo Sirainen return -1;
1032e5427bf10566098f3b3bb9110e2bc1227e85Timo Sirainen }
1032e5427bf10566098f3b3bb9110e2bc1227e85Timo Sirainen if (!dest->copy_input->eof) {
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen fs_set_error_async(dest->fs);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen return -1;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen }
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen i_stream_unref(&dest->copy_input);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen if (fs_write_stream_finish(dest, &dest->copy_output) < 0)
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen return -1;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen dest->copy_src = NULL;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen return 0;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen}
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainenint fs_copy(struct fs_file *src, struct fs_file *dest)
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen{
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen i_assert(src->fs == dest->fs);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen return src->fs->v.copy(src, dest);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen}
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainenint fs_copy_finish_async(struct fs_file *dest)
41bb0aa8e357876bc9a1916a37c9e3e78e5f8185Timo Sirainen{
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen return dest->fs->v.copy(NULL, dest);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen}
dd8de60250511cc729b67249e61dfc6b4debff11Timo Sirainen
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainenint fs_rename(struct fs_file *src, struct fs_file *dest)
b9ec0443d7d8afebfe61c17a9d692d6fad30c276Timo Sirainen{
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen i_assert(src->fs == dest->fs);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return src->fs->v.rename(src, dest);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainen
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainenint fs_delete(struct fs_file *file)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen return file->fs->v.delete_file(file);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainenstruct fs_iter *
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainenfs_iter_init(struct fs *fs, const char *path, enum fs_iter_flags flags)
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainen{
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainen return fs->v.iter_init(fs, path, flags);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainenint fs_iter_deinit(struct fs_iter **_iter)
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen{
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen struct fs_iter *iter = *_iter;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen
41bb0aa8e357876bc9a1916a37c9e3e78e5f8185Timo Sirainen *_iter = NULL;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen return iter->fs->v.iter_deinit(iter);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen}
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenconst char *fs_iter_next(struct fs_iter *iter)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
51920d00fa50edf7b2e9b1019288d64b7abee7f3Timo Sirainen return iter->fs->v.iter_next(iter);
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen}
51920d00fa50edf7b2e9b1019288d64b7abee7f3Timo Sirainen
21ec6628c567eeff025af35d8027be01044b0b1aTimo Sirainenvoid fs_set_error(struct fs *fs, const char *fmt, ...)
21ec6628c567eeff025af35d8027be01044b0b1aTimo Sirainen{
21ec6628c567eeff025af35d8027be01044b0b1aTimo Sirainen va_list args;
21ec6628c567eeff025af35d8027be01044b0b1aTimo Sirainen
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen va_start(args, fmt);
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen str_truncate(fs->last_error, 0);
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen str_vprintfa(fs->last_error, fmt, args);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen va_end(args);
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen}
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainenvoid fs_set_critical(struct fs *fs, const char *fmt, ...)
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen{
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen va_list args;
b9ec0443d7d8afebfe61c17a9d692d6fad30c276Timo Sirainen
b9ec0443d7d8afebfe61c17a9d692d6fad30c276Timo Sirainen va_start(args, fmt);
b9ec0443d7d8afebfe61c17a9d692d6fad30c276Timo Sirainen str_truncate(fs->last_error, 0);
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen str_vprintfa(fs->last_error, fmt, args);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("fs-%s: %s", fs->name, str_c(fs->last_error));
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen va_end(args);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen}
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenvoid fs_set_error_async(struct fs *fs)
cd5ee8630497fdbd853ef588a858b4ef619a5e03Timo Sirainen{
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen fs_set_error(fs, "Asynchronous operation in progress");
fd2118e34f4d1d65cffdccc40d74dda931fae81eTimo Sirainen errno = EAGAIN;
fd2118e34f4d1d65cffdccc40d74dda931fae81eTimo Sirainen}
fd2118e34f4d1d65cffdccc40d74dda931fae81eTimo Sirainen