bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2016-2018 Dovecot authors, see the included COPYING file */
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen#include "lib.h"
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen#include "istream.h"
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen#include "ostream.h"
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen#include "test-common.h"
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen#include "fs-test.h"
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic struct fs *fs_test_alloc(void)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen struct test_fs *fs;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs = i_new(struct test_fs, 1);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs->fs = fs_class_test;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen i_array_init(&fs->iter_files, 32);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return &fs->fs;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic int
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenfs_test_init(struct fs *_fs ATTR_UNUSED, const char *args ATTR_UNUSED,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen const struct fs_settings *set ATTR_UNUSED)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return 0;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic void fs_test_deinit(struct fs *_fs)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen struct test_fs *fs = (struct test_fs *)_fs;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen array_free(&fs->iter_files);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen i_free(fs);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic enum fs_properties fs_test_get_properties(struct fs *_fs)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen struct test_fs *fs = (struct test_fs *)_fs;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return fs->properties;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
86ad48a2e740bd63a9b7299d7f3e229831d9b303Timo Sirainenstatic struct fs_file *fs_test_file_alloc(void)
86ad48a2e740bd63a9b7299d7f3e229831d9b303Timo Sirainen{
86ad48a2e740bd63a9b7299d7f3e229831d9b303Timo Sirainen struct test_fs_file *file = i_new(struct test_fs_file, 1);
86ad48a2e740bd63a9b7299d7f3e229831d9b303Timo Sirainen return &file->file;
86ad48a2e740bd63a9b7299d7f3e229831d9b303Timo Sirainen}
86ad48a2e740bd63a9b7299d7f3e229831d9b303Timo Sirainen
86ad48a2e740bd63a9b7299d7f3e229831d9b303Timo Sirainenstatic void
86ad48a2e740bd63a9b7299d7f3e229831d9b303Timo Sirainenfs_test_file_init(struct fs_file *_file, const char *path,
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen enum fs_open_mode mode, enum fs_open_flags flags)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
86ad48a2e740bd63a9b7299d7f3e229831d9b303Timo Sirainen struct test_fs_file *file = (struct test_fs_file *)_file;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen file->file.path = i_strdup(path);
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen file->file.flags = flags;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen file->mode = mode;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen file->contents = buffer_create_dynamic(default_pool, 1024);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen file->exists = TRUE;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen file->seekable = TRUE;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen file->wait_async = (flags & FS_OPEN_FLAG_ASYNC) != 0;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic void fs_test_file_deinit(struct fs_file *_file)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen struct test_fs_file *file = (struct test_fs_file *)_file;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen buffer_free(&file->contents);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen i_free(file->file.path);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen i_free(file);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic void fs_test_file_close(struct fs_file *_file)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen struct test_fs_file *file = (struct test_fs_file *)_file;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen file->closed = TRUE;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic const char *fs_test_file_get_path(struct fs_file *_file)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return _file->path;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic void
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenfs_test_set_async_callback(struct fs_file *_file,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_file_async_callback_t *callback,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen void *context)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen struct test_fs_file *file = (struct test_fs_file *)_file;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen file->async_callback = callback;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen file->async_context = context;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
d34b8a75f3b74e26adc85b6436d033b1dcfaf9daTimo Sirainenstatic void fs_test_wait_async(struct fs *_fs ATTR_UNUSED)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic void
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenfs_test_set_metadata(struct fs_file *_file, const char *key,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen const char *value)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_default_set_metadata(_file, key, value);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic int
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenfs_test_get_metadata(struct fs_file *_file,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen const ARRAY_TYPE(fs_metadata) **metadata_r)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen struct test_fs_file *file = (struct test_fs_file *)_file;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen if (file->wait_async) {
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen fs_set_error_async(_file->fs);
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen return -1;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen }
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen if (file->io_failure) {
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen errno = EIO;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen return -1;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen }
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_metadata_init(_file);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen *metadata_r = &_file->metadata;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return 0;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic bool fs_test_prefetch(struct fs_file *_file ATTR_UNUSED,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen uoff_t length ATTR_UNUSED)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen struct test_fs_file *file = (struct test_fs_file *)_file;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen file->prefetched = TRUE;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return TRUE;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic void fs_test_stream_destroyed(struct test_fs_file *file)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen i_assert(file->input != NULL);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen file->input = NULL;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic struct istream *
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenfs_test_read_stream(struct fs_file *_file, size_t max_buffer_size ATTR_UNUSED)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen struct test_fs_file *file = (struct test_fs_file *)_file;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen struct istream *input;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen i_assert(file->input == NULL);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen if (!file->exists)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return i_stream_create_error(ENOENT);
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen if (file->io_failure)
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen return i_stream_create_error(EIO);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen input = test_istream_create_data(file->contents->data,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen file->contents->used);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen i_stream_add_destroy_callback(input, fs_test_stream_destroyed, file);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen if (!file->seekable)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen input->seekable = FALSE;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen file->input = input;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return input;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic void fs_test_write_stream(struct fs_file *_file)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen struct test_fs_file *file = (struct test_fs_file *)_file;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen i_assert(_file->output == NULL);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen buffer_set_used_size(file->contents, 0);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen _file->output = o_stream_create_buffer(file->contents);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic int fs_test_write_stream_finish(struct fs_file *_file, bool success)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen struct test_fs_file *file = (struct test_fs_file *)_file;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
be5773cb4d6edae8a5d9f300c3c7375cdd33826eJosef 'Jeff' Sipek o_stream_destroy(&_file->output);
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen if (file->wait_async) {
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen fs_set_error_async(_file->fs);
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen return 0;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen }
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen if (file->io_failure)
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen success = FALSE;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen if (!success)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen buffer_set_used_size(file->contents, 0);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return success ? 1 : -1;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic int
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenfs_test_lock(struct fs_file *_file, unsigned int secs ATTR_UNUSED,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen struct fs_lock **lock_r)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen struct test_fs_file *file = (struct test_fs_file *)_file;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen if (file->locked)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return 0;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen file->locked = TRUE;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen *lock_r = i_new(struct fs_lock, 1);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen (*lock_r)->file = _file;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return 1;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic void fs_test_unlock(struct fs_lock *lock)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen struct test_fs_file *file = (struct test_fs_file *)lock->file;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen file->locked = FALSE;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen i_free(lock);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic int fs_test_exists(struct fs_file *_file)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen struct test_fs_file *file = (struct test_fs_file *)_file;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen if (file->wait_async) {
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen fs_set_error_async(_file->fs);
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen return -1;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen }
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen if (file->io_failure) {
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen errno = EIO;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen return -1;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen }
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return file->exists ? 1 : 0;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic int fs_test_stat(struct fs_file *_file, struct stat *st_r)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen struct test_fs_file *file = (struct test_fs_file *)_file;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen if (file->wait_async) {
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen fs_set_error_async(_file->fs);
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen return -1;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen }
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen if (file->io_failure) {
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen errno = EIO;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen return -1;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen }
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen if (!file->exists) {
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen errno = ENOENT;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return -1;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen }
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(st_r);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen st_r->st_size = file->contents->used;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return 0;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic int fs_test_copy(struct fs_file *_src, struct fs_file *_dest)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen struct test_fs_file *src;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen struct test_fs_file *dest = (struct test_fs_file *)_dest;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen if (_src != NULL)
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen dest->copy_src = test_fs_file_get(_src->fs, fs_file_path(_src));
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen src = dest->copy_src;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen if (dest->wait_async) {
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen fs_set_error_async(_dest->fs);
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen return -1;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen }
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen dest->copy_src = NULL;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen if (dest->io_failure) {
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen errno = EIO;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen return -1;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen }
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen if (!src->exists) {
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen errno = ENOENT;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return -1;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen }
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen buffer_set_used_size(dest->contents, 0);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen buffer_append_buf(dest->contents, src->contents, 0, (size_t)-1);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen dest->exists = TRUE;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return 0;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic int fs_test_rename(struct fs_file *_src, struct fs_file *_dest)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen struct test_fs_file *src = (struct test_fs_file *)_src;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen struct test_fs_file *dest = (struct test_fs_file *)_dest;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen if (src->wait_async || dest->wait_async) {
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen fs_set_error_async(_dest->fs);
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen return -1;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen }
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen if (fs_test_copy(_src, _dest) < 0)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return -1;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen src->exists = FALSE;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return 0;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic int fs_test_delete(struct fs_file *_file)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen struct test_fs_file *file = (struct test_fs_file *)_file;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen if (file->wait_async) {
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen fs_set_error_async(_file->fs);
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen return -1;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen }
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen if (!file->exists) {
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen errno = ENOENT;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return -1;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen }
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return 0;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
4d71d712b42285afbd2a997f3408142ef0d5f899Timo Sirainenstatic struct fs_iter *fs_test_iter_alloc(void)
4d71d712b42285afbd2a997f3408142ef0d5f899Timo Sirainen{
4d71d712b42285afbd2a997f3408142ef0d5f899Timo Sirainen struct test_fs_iter *iter = i_new(struct test_fs_iter, 1);
4d71d712b42285afbd2a997f3408142ef0d5f899Timo Sirainen return &iter->iter;
4d71d712b42285afbd2a997f3408142ef0d5f899Timo Sirainen}
4d71d712b42285afbd2a997f3408142ef0d5f899Timo Sirainen
4d71d712b42285afbd2a997f3408142ef0d5f899Timo Sirainenstatic void
4d71d712b42285afbd2a997f3408142ef0d5f899Timo Sirainenfs_test_iter_init(struct fs_iter *_iter, const char *path,
4110f968c96680d61ca47bd7a903a254b911addaTimo Sirainen enum fs_iter_flags flags ATTR_UNUSED)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
4d71d712b42285afbd2a997f3408142ef0d5f899Timo Sirainen struct test_fs_iter *iter = (struct test_fs_iter *)_iter;
4d71d712b42285afbd2a997f3408142ef0d5f899Timo Sirainen struct test_fs *fs = (struct test_fs *)_iter->fs;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen iter->prefix = i_strdup(path);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen iter->prefix_len = strlen(iter->prefix);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen iter->prev_dir = i_strdup("");
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen array_sort(&fs->iter_files, i_strcmp_p);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic const char *fs_test_iter_next(struct fs_iter *_iter)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen struct test_fs_iter *iter = (struct test_fs_iter *)_iter;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen struct test_fs *fs = (struct test_fs *)_iter->fs;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen const char *const *files, *p;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen unsigned int count;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t len, prev_dir_len = strlen(iter->prev_dir);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen files = array_get(&fs->iter_files, &count);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen for (; iter->idx < count; iter->idx++) {
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen const char *fname = files[iter->idx];
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen if (strncmp(fname, iter->prefix, iter->prefix_len) != 0)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen continue;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen p = strrchr(fname, '/');
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen if ((_iter->flags & FS_ITER_FLAG_DIRS) == 0) {
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen if (p == NULL)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return fname;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen if (p[1] == '\0')
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen continue; /* dir/ */
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return p+1;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen }
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen if (p == NULL)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen continue;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen len = p - fname;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen if (len == 0)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen continue;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen if (len == prev_dir_len &&
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen strncmp(fname, iter->prev_dir, len) == 0)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen continue;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen i_free(iter->prev_dir);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen iter->prev_dir = i_strndup(fname, len);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return iter->prev_dir;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen }
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return NULL;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenstatic int fs_test_iter_deinit(struct fs_iter *_iter)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen struct test_fs_iter *iter = (struct test_fs_iter *)_iter;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen int ret = iter->failed ? -1 : 0;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen i_free(iter->prefix);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen i_free(iter);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return ret;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainenstruct test_fs *test_fs_get(struct fs *fs)
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen{
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen while (strcmp(fs->name, "test") != 0) {
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen i_assert(fs->parent != NULL);
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs = fs->parent;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen }
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen return (struct test_fs *)fs;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen}
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainenstruct test_fs_file *test_fs_file_get(struct fs *fs, const char *path)
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen{
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen struct fs_file *file;
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen fs = &test_fs_get(fs)->fs;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen for (file = fs->files;; file = file->next) {
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen i_assert(file != NULL);
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen if (strcmp(fs_file_path(file), path) == 0)
b162e16ade1e0d9bfae62e366caf57a3132f5963Timo Sirainen break;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen }
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen return (struct test_fs_file *)file;
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen}
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainenconst struct fs fs_class_test = {
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen .name = "test",
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen .v = {
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_alloc,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_init,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_deinit,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_get_properties,
86ad48a2e740bd63a9b7299d7f3e229831d9b303Timo Sirainen fs_test_file_alloc,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_file_init,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_file_deinit,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_file_close,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_file_get_path,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_set_async_callback,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_wait_async,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_set_metadata,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_get_metadata,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_prefetch,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen NULL,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_read_stream,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen NULL,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_write_stream,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_write_stream_finish,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_lock,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_unlock,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_exists,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_stat,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_copy,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_rename,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_delete,
4d71d712b42285afbd2a997f3408142ef0d5f899Timo Sirainen fs_test_iter_alloc,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_iter_init,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen fs_test_iter_next,
8296531314913c7f9d4ab1857c6f79ff1308a12fTimo Sirainen fs_test_iter_deinit,
a63cd84128875485e40ed804dbf0b0945526989cTimo Sirainen NULL,
a63cd84128875485e40ed804dbf0b0945526989cTimo Sirainen NULL,
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen }
140afad728d78c56fb4c0256f94eb81a213688dbTimo Sirainen};