1
/* Copyright (c) 2010-2012 Dovecot authors, see the included COPYING file */
1
/* Copyright (c) 2010-2013 Dovecot authors, see the included COPYING file */
5
#include "module-dir.h"
7
#include "hash-method.h"
9
#include "istream-seekable.h"
5
11
#include "fs-api-private.h"
7
static struct fs *fs_classes[] = {
13
static struct module *fs_modules = NULL;
14
static ARRAY(const struct fs *) fs_classes;
14
17
fs_alloc(const struct fs *fs_class, const char *args,
15
const struct fs_settings *set)
18
const struct fs_settings *set, struct fs **fs_r, const char **error_r)
19
fs = fs_class->v.init(args, set);
23
fs = fs_class->v.alloc();
20
24
fs->last_error = str_new(default_pool, 64);
24
struct fs *fs_init(const char *driver, const char *args,
25
const struct fs_settings *set)
29
for (i = 0; i < N_ELEMENTS(fs_classes); i++) {
30
if (strcmp(fs_classes[i]->name, driver) == 0)
31
return fs_alloc(fs_classes[i], args, set);
33
i_fatal("Unknown fs driver: %s", driver);
27
ret = fs_class->v.init(fs, args, set);
30
/* a bit kludgy way to allow data stack frame usage in normal
31
conditions but still be able to return error message from
33
*error_r = t_strdup_printf("%s: %s", fs_class->name,
42
static void fs_class_register(const struct fs *fs_class)
44
array_append(&fs_classes, &fs_class, 1);
47
static void fs_classes_deinit(void)
49
array_free(&fs_classes);
52
static void fs_classes_init(void)
54
i_array_init(&fs_classes, 8);
55
fs_class_register(&fs_class_posix);
56
fs_class_register(&fs_class_metawrap);
57
fs_class_register(&fs_class_sis);
58
fs_class_register(&fs_class_sis_queue);
59
lib_atexit(fs_classes_deinit);
62
static const struct fs *fs_class_find(const char *driver)
64
const struct fs *const *classp;
66
if (!array_is_created(&fs_classes))
69
array_foreach(&fs_classes, classp) {
70
if (strcmp((*classp)->name, driver) == 0)
76
static void fs_class_deinit_modules(void)
78
module_dir_unload(&fs_modules);
81
static void fs_class_try_load_plugin(const char *driver)
83
const char *module_name = t_strdup_printf("fs_%s", driver);
84
struct module *module;
85
struct module_dir_load_settings mod_set;
86
const struct fs *fs_class;
88
memset(&mod_set, 0, sizeof(mod_set));
89
mod_set.abi_version = DOVECOT_ABI_VERSION;
90
mod_set.ignore_missing = TRUE;
92
fs_modules = module_dir_load_missing(fs_modules, MODULE_DIR,
93
module_name, &mod_set);
94
module_dir_init(fs_modules);
96
module = module_dir_find(fs_modules, module_name);
97
fs_class = module == NULL ? NULL :
98
module_get_symbol(module, t_strdup_printf("fs_class_%s", driver));
100
fs_class_register(fs_class);
102
lib_atexit(fs_class_deinit_modules);
105
int fs_init(const char *driver, const char *args,
106
const struct fs_settings *set,
107
struct fs **fs_r, const char **error_r)
109
const struct fs *fs_class;
110
const char *temp_file_prefix;
112
fs_class = fs_class_find(driver);
113
if (fs_class == NULL) {
115
fs_class_try_load_plugin(driver);
117
fs_class = fs_class_find(driver);
119
if (fs_class == NULL) {
120
*error_r = t_strdup_printf("Unknown fs driver: %s", driver);
123
if (fs_alloc(fs_class, args, set, fs_r, error_r) < 0)
126
temp_file_prefix = set->temp_file_prefix != NULL ?
127
set->temp_file_prefix : ".temp.dovecot";
128
(*fs_r)->temp_path_prefix = i_strconcat(set->temp_dir, "/",
129
temp_file_prefix, NULL);
36
133
void fs_deinit(struct fs **_fs)
38
135
struct fs *fs = *_fs;
136
string_t *last_error = fs->last_error;
44
142
fs->name, fs->files_open_count);
47
str_free(&fs->last_error);
145
i_free(fs->temp_path_prefix);
51
int fs_open(struct fs *fs, const char *path, int mode_flags,
52
struct fs_file **file_r)
147
str_free(&last_error);
150
const char *fs_get_root_driver(struct fs *fs)
152
while (fs->parent != NULL)
157
struct fs_file *fs_file_init(struct fs *fs, const char *path, int mode_flags)
159
struct fs_file *file;
161
i_assert(path != NULL);
162
i_assert((mode_flags & FS_OPEN_FLAG_ASYNC_NOQUEUE) == 0 ||
163
(mode_flags & FS_OPEN_FLAG_ASYNC) != 0);
57
ret = fs->v.open(fs, path, mode_flags & FS_OPEN_MODE_MASK,
58
mode_flags & ~FS_OPEN_MODE_MASK, file_r);
166
file = fs->v.file_init(fs, path, mode_flags & FS_OPEN_MODE_MASK,
167
mode_flags & ~FS_OPEN_MODE_MASK);
61
fs->files_open_count++;
169
file->flags = mode_flags & ~FS_OPEN_MODE_MASK;
170
fs->files_open_count++;
65
void fs_close(struct fs_file **_file)
174
void fs_file_deinit(struct fs_file **_file)
67
176
struct fs_file *file = *_file;
177
pool_t metadata_pool = file->metadata_pool;
69
179
i_assert(file->fs->files_open_count > 0);
73
185
file->fs->files_open_count--;
74
file->fs->v.close(file);
187
file->fs->v.file_deinit(file);
190
if (metadata_pool != NULL)
191
pool_unref(&metadata_pool);
194
void fs_file_close(struct fs_file *file)
196
if (file->pending_read_input != NULL)
197
i_stream_unref(&file->pending_read_input);
198
if (file->seekable_input != NULL)
199
i_stream_unref(&file->seekable_input);
201
if (file->copy_input != NULL) {
202
i_stream_unref(&file->copy_input);
203
(void)fs_write_stream_abort(file, &file->copy_output);
205
i_free_and_null(file->write_digest);
206
if (file->fs->v.file_close != NULL) T_BEGIN {
207
file->fs->v.file_close(file);
211
enum fs_properties fs_get_properties(struct fs *fs)
213
return fs->v.get_properties(fs);
216
void fs_metadata_init(struct fs_file *file)
218
if (file->metadata_pool == NULL) {
219
file->metadata_pool = pool_alloconly_create("fs metadata", 1024);
220
p_array_init(&file->metadata, file->metadata_pool, 8);
224
void fs_default_set_metadata(struct fs_file *file,
225
const char *key, const char *value)
227
struct fs_metadata *metadata;
229
fs_metadata_init(file);
230
metadata = array_append_space(&file->metadata);
231
metadata->key = p_strdup(file->metadata_pool, key);
232
metadata->value = p_strdup(file->metadata_pool, value);
235
void fs_set_metadata(struct fs_file *file, const char *key, const char *value)
237
if (file->fs->v.set_metadata != NULL) T_BEGIN {
238
file->fs->v.set_metadata(file, key, value);
242
int fs_get_metadata(struct fs_file *file,
243
const ARRAY_TYPE(fs_metadata) **metadata_r)
245
if (file->fs->v.get_metadata == NULL) {
246
fs_set_error(file->fs, "Metadata not supported by backend");
249
return file->fs->v.get_metadata(file, metadata_r);
77
252
const char *fs_file_path(struct fs_file *file)
254
return file->fs->v.get_path == NULL ? file->path :
255
file->fs->v.get_path(file);
258
struct fs *fs_file_fs(struct fs_file *file)
263
static void ATTR_FORMAT(2, 0)
264
fs_set_verror(struct fs *fs, const char *fmt, va_list args)
266
/* the error is always kept in the parentmost fs */
267
if (fs->parent != NULL)
268
fs_set_verror(fs->parent, fmt, args);
270
str_truncate(fs->last_error, 0);
271
str_vprintfa(fs->last_error, fmt, args);
82
275
const char *fs_last_error(struct fs *fs)
277
/* the error is always kept in the parentmost fs */
278
if (fs->parent != NULL)
279
return fs_last_error(fs->parent);
84
281
if (str_len(fs->last_error) == 0)
85
282
return "BUG: Unknown fs error";
86
283
return str_c(fs->last_error);
91
288
return fs_last_error(file->fs);
291
bool fs_prefetch(struct fs_file *file, uoff_t length)
296
ret = file->fs->v.prefetch(file, length);
301
ssize_t fs_read_via_stream(struct fs_file *file, void *buf, size_t size)
303
const unsigned char *data;
309
if (file->pending_read_input == NULL)
310
file->pending_read_input = fs_read_stream(file, size+1);
311
ret = i_stream_read_data(file->pending_read_input,
312
&data, &data_size, size-1);
314
fs_set_error_async(file->fs);
317
if (ret < 0 && file->pending_read_input->stream_errno != 0) {
318
fs_set_error(file->fs, "read(%s) failed: %m",
319
i_stream_get_name(file->pending_read_input));
321
ret = I_MIN(size, data_size);
322
memcpy(buf, data, ret);
324
i_stream_unref(&file->pending_read_input);
94
328
ssize_t fs_read(struct fs_file *file, void *buf, size_t size)
96
return file->fs->v.read(file, buf, size);
332
if (file->fs->v.read != NULL) {
334
ret = file->fs->v.read(file, buf, size);
339
/* backend didn't bother to implement read(), but we can do it with
341
return fs_read_via_stream(file, buf, size);
99
344
struct istream *fs_read_stream(struct fs_file *file, size_t max_buffer_size)
101
return file->fs->v.read_stream(file, max_buffer_size);
346
struct istream *input, *inputs[2];
347
const unsigned char *data;
350
bool want_seekable = FALSE;
352
if (file->seekable_input != NULL) {
353
i_stream_seek(file->seekable_input, 0);
354
i_stream_ref(file->seekable_input);
355
return file->seekable_input;
358
input = file->fs->v.read_stream(file, max_buffer_size);
360
if (input->stream_errno != 0) {
361
/* read failed already */
365
if ((file->flags & FS_OPEN_FLAG_SEEKABLE) != 0)
366
want_seekable = TRUE;
367
else if ((file->flags & FS_OPEN_FLAG_ASYNC) == 0 && !input->blocking)
368
want_seekable = TRUE;
370
if (want_seekable && !input->seekable) {
371
/* need to make the stream seekable */
374
input = i_stream_create_seekable_path(inputs, max_buffer_size,
375
file->fs->temp_path_prefix);
376
i_stream_set_name(input, i_stream_get_name(inputs[0]));
377
i_stream_unref(&inputs[0]);
379
file->seekable_input = input;
380
i_stream_ref(file->seekable_input);
382
if ((file->flags & FS_OPEN_FLAG_ASYNC) == 0 && !input->blocking) {
383
/* read the whole input stream before returning */
384
while ((ret = i_stream_read_data(input, &data, &size, 0)) >= 0) {
385
i_stream_skip(input, size);
387
if (fs_wait_async(file->fs) < 0) {
388
input->stream_errno = errno;
394
i_stream_seek(input, 0);
399
int fs_write_via_stream(struct fs_file *file, const void *data, size_t size)
401
struct ostream *output;
405
if (!file->write_pending) {
406
output = fs_write_stream(file);
407
if ((ret = o_stream_send(output, data, size)) < 0) {
409
fs_set_error(file->fs, "fs_write(%s) failed: %m",
410
o_stream_get_name(output));
411
fs_write_stream_abort(file, &output);
415
i_assert((size_t)ret == size);
416
ret = fs_write_stream_finish(file, &output);
418
ret = fs_write_stream_finish_async(file);
421
fs_set_error_async(file->fs);
422
file->write_pending = TRUE;
425
file->write_pending = FALSE;
426
return ret < 0 ? -1 : 0;
104
429
int fs_write(struct fs_file *file, const void *data, size_t size)
106
return file->fs->v.write(file, data, size);
433
if (file->fs->v.write != NULL) {
435
ret = file->fs->v.write(file, data, size);
440
/* backend didn't bother to implement write(), but we can do it with
442
return fs_write_via_stream(file, data, size);
109
445
struct ostream *fs_write_stream(struct fs_file *file)
111
file->fs->v.write_stream(file);
448
file->fs->v.write_stream(file);
112
450
i_assert(file->output != NULL);
113
451
return file->output;
116
454
int fs_write_stream_finish(struct fs_file *file, struct ostream **output)
118
i_assert(*output == file->output);
458
i_assert(*output == file->output || *output == NULL);
121
return file->fs->v.write_stream_finish(file, TRUE);
462
ret = file->fs->v.write_stream_finish(file, TRUE);
467
int fs_write_stream_finish_async(struct fs_file *file)
472
ret = file->fs->v.write_stream_finish(file, TRUE);
124
477
void fs_write_stream_abort(struct fs_file *file, struct ostream **output)
126
479
i_assert(*output == file->output);
129
(void)file->fs->v.write_stream_finish(file, FALSE);
483
(void)file->fs->v.write_stream_finish(file, FALSE);
487
void fs_write_set_hash(struct fs_file *file, const struct hash_method *method,
490
file->write_digest_method = method;
492
i_free(file->write_digest);
493
file->write_digest = i_malloc(method->digest_size);
494
memcpy(file->write_digest, digest, method->digest_size);
497
void fs_file_set_async_callback(struct fs_file *file,
498
fs_file_async_callback_t *callback,
501
if (file->fs->v.set_async_callback != NULL)
502
file->fs->v.set_async_callback(file, callback, context);
507
int fs_wait_async(struct fs *fs)
511
if (fs->v.wait_async == NULL)
514
ret = fs->v.wait_async(fs);
132
519
int fs_lock(struct fs_file *file, unsigned int secs, struct fs_lock **lock_r)
134
return file->fs->v.lock(file, secs, lock_r);
524
ret = file->fs->v.lock(file, secs, lock_r);
137
529
void fs_unlock(struct fs_lock **_lock)
139
531
struct fs_lock *lock = *_lock;
142
lock->file->fs->v.unlock(lock);
145
int fs_fdatasync(struct fs_file *file)
147
return file->fs->v.fdatasync(file);
150
int fs_exists(struct fs *fs, const char *path)
152
return fs->v.exists(fs, path);
155
int fs_stat(struct fs *fs, const char *path, struct stat *st_r)
157
return fs->v.stat(fs, path, st_r);
160
int fs_link(struct fs *fs, const char *src, const char *dest)
162
return fs->v.link(fs, src, dest);
165
int fs_rename(struct fs *fs, const char *src, const char *dest)
167
return fs->v.rename(fs, src, dest);
170
int fs_unlink(struct fs *fs, const char *path)
172
return fs->v.unlink(fs, path);
175
int fs_rmdir(struct fs *fs, const char *path)
177
return fs->v.rmdir(fs, path);
535
lock->file->fs->v.unlock(lock);
539
int fs_exists(struct fs_file *file)
544
if (file->fs->v.exists == NULL) {
545
/* fallback to stat() */
546
if (fs_stat(file, &st) == 0)
549
return errno == ENOENT ? 0 : -1;
552
ret = file->fs->v.exists(file);
557
int fs_stat(struct fs_file *file, struct stat *st_r)
562
ret = file->fs->v.stat(file, st_r);
567
int fs_default_copy(struct fs_file *src, struct fs_file *dest)
569
if (dest->copy_src != NULL) {
570
i_assert(src == NULL || src == dest->copy_src);
571
if (dest->copy_output == NULL) {
572
i_assert(dest->copy_input == NULL);
573
if (fs_write_stream_finish_async(dest) <= 0)
575
dest->copy_src = NULL;
579
dest->copy_src = src;
580
dest->copy_input = fs_read_stream(src, IO_BLOCK_SIZE);
581
dest->copy_output = fs_write_stream(dest);
583
while (o_stream_send_istream(dest->copy_output, dest->copy_input) > 0) ;
584
if (dest->copy_input->stream_errno != 0) {
585
errno = dest->copy_input->stream_errno;
586
fs_set_error(dest->fs, "read(%s) failed: %m",
587
i_stream_get_name(dest->copy_input));
588
i_stream_unref(&dest->copy_input);
589
fs_write_stream_abort(dest, &dest->copy_output);
592
if (dest->copy_output->stream_errno != 0) {
593
errno = dest->copy_output->stream_errno;
594
fs_set_error(dest->fs, "write(%s) failed: %m",
595
o_stream_get_name(dest->copy_output));
596
i_stream_unref(&dest->copy_input);
597
fs_write_stream_abort(dest, &dest->copy_output);
600
if (!dest->copy_input->eof) {
601
fs_set_error_async(dest->fs);
604
i_stream_unref(&dest->copy_input);
605
if (fs_write_stream_finish(dest, &dest->copy_output) <= 0)
607
dest->copy_src = NULL;
611
int fs_copy(struct fs_file *src, struct fs_file *dest)
615
i_assert(src->fs == dest->fs);
618
ret = src->fs->v.copy(src, dest);
623
int fs_copy_finish_async(struct fs_file *dest)
628
ret = dest->fs->v.copy(NULL, dest);
633
int fs_rename(struct fs_file *src, struct fs_file *dest)
637
i_assert(src->fs == dest->fs);
640
ret = src->fs->v.rename(src, dest);
645
int fs_delete(struct fs_file *file)
650
ret = file->fs->v.delete_file(file);
656
fs_iter_init(struct fs *fs, const char *path, enum fs_iter_flags flags)
658
struct fs_iter *iter;
661
iter = fs->v.iter_init(fs, path, flags);
666
int fs_iter_deinit(struct fs_iter **_iter)
668
struct fs_iter *iter = *_iter;
673
ret = iter->fs->v.iter_deinit(iter);
678
const char *fs_iter_next(struct fs_iter *iter)
680
return iter->fs->v.iter_next(iter);
683
void fs_iter_set_async_callback(struct fs_iter *iter,
684
fs_file_async_callback_t *callback,
687
iter->async_callback = callback;
688
iter->async_context = context;
691
bool fs_iter_have_more(struct fs_iter *iter)
693
return iter->async_have_more;
180
696
void fs_set_error(struct fs *fs, const char *fmt, ...)