static void test_fs_async_copy(const char *test_name, struct fs *fs) { struct fs_file *src, *dest; struct test_fs_file *test_file; test_begin(t_strdup_printf("%s: async copy", test_name)); src = fs_file_init(fs, "foo", FS_OPEN_MODE_REPLACE); test_assert(fs_write(src, "source", 6) == 0); dest = fs_file_init(fs, "bar", FS_OPEN_MODE_REPLACE | FS_OPEN_FLAG_ASYNC); test_assert(fs_copy(src, dest) == -1 && errno == EAGAIN); test_file = test_fs_file_get(fs, "bar"); test_file->wait_async = FALSE; test_assert(fs_copy_finish_async(dest) == 0); test_assert(test_file->contents->used > 0); fs_file_deinit(&dest); fs_file_deinit(&src); test_end(); }
static struct fs_file * fs_compress_file_init(struct fs *_fs, const char *path, enum fs_open_mode mode, enum fs_open_flags flags) { struct compress_fs *fs = (struct compress_fs *)_fs; struct compress_fs_file *file; file = i_new(struct compress_fs_file, 1); file->file.fs = _fs; file->file.path = i_strdup(path); file->fs = fs; file->open_mode = mode; /* avoid unnecessarily creating two seekable streams */ flags &= ~FS_OPEN_FLAG_SEEKABLE; file->file.parent = fs_file_init(_fs->parent, path, mode | flags); if (mode == FS_OPEN_MODE_READONLY && (flags & FS_OPEN_FLAG_ASYNC) == 0) { /* use async stream for parent, so fs_read_stream() won't create another seekable stream unneededly */ file->super_read = fs_file_init(_fs->parent, path, mode | flags | FS_OPEN_FLAG_ASYNC); } else { file->super_read = file->file.parent; } return &file->file; }
static struct fs_file * fs_sis_file_init(struct fs *_fs, const char *path, enum fs_open_mode mode, enum fs_open_flags flags) { struct sis_fs *fs = (struct sis_fs *)_fs; struct sis_fs_file *file; const char *dir, *hash; file = i_new(struct sis_fs_file, 1); file->file.fs = _fs; file->file.path = i_strdup(path); file->fs = fs; file->open_mode = mode; if (mode == FS_OPEN_MODE_APPEND) { fs_set_error(_fs, "APPEND mode not supported"); return &file->file; } if (fs_sis_path_parse(_fs, path, &dir, &hash) < 0) { fs_set_error(_fs, "Invalid path"); return &file->file; } /* if hashes/<hash> already exists, open it */ file->hash_path = i_strdup_printf("%s/"HASH_DIR_NAME"/%s", dir, hash); file->hash_file = fs_file_init(_fs->parent, file->hash_path, FS_OPEN_MODE_READONLY); file->hash_input = fs_read_stream(file->hash_file, IO_BLOCK_SIZE); if (i_stream_read(file->hash_input) == -1) { /* doesn't exist */ if (errno != ENOENT) { i_error("fs-sis: Couldn't read hash file %s: %m", file->hash_path); } i_stream_destroy(&file->hash_input); } file->super = fs_file_init(_fs->parent, path, mode | flags); return &file->file; }
static void test_fs_metawrap_write_empty(void) { struct fs *fs; const char *error; test_begin("fs metawrap write empty file"); if (fs_init("metawrap", "test", &fs_set, &fs, &error) < 0) i_fatal("fs_init() failed: %s", error); struct fs_file *file = fs_file_init(fs, "foo", FS_OPEN_MODE_REPLACE); struct ostream *output = fs_write_stream(file); test_assert(fs_write_stream_finish(file, &output) > 0); fs_file_deinit(&file); fs_deinit(&fs); test_end(); }
/* * File system initialization */ EXPORT INT fs_init(fs_env_t *env, const fs_config_t *config) { INT sts; sts = fs_file_init(config->c_maxfile); if (sts == 0) { sts = fs_fimp_init(config->c_maxfimp); if (sts == 0) { sts = fs_con_init(config->c_maxcon); if (sts == 0) { sts = fs_rootinit(env); } } } return sts; }
static struct fs_file * fs_sis_queue_file_init(struct fs *_fs, const char *path, enum fs_open_mode mode, enum fs_open_flags flags) { struct sis_queue_fs *fs = (struct sis_queue_fs *)_fs; struct sis_queue_fs_file *file; file = i_new(struct sis_queue_fs_file, 1); file->file.fs = _fs; file->file.path = i_strdup(path); file->fs = fs; if (mode == FS_OPEN_MODE_APPEND) fs_set_error(_fs, "APPEND mode not supported"); else file->super = fs_file_init(fs->super, path, mode | flags); return &file->file; }
static void test_fs_async_write(const char *test_name, struct fs *fs) { struct fs_file *file; struct test_fs_file *test_file; struct ostream *output; unsigned int i; test_begin(t_strdup_printf("%s: async write", test_name)); for (i = 0; i < 3; i++) { file = fs_file_init(fs, "foo", FS_OPEN_MODE_REPLACE | FS_OPEN_FLAG_ASYNC); output = fs_write_stream(file); o_stream_nsend_str(output, "12345"); if (i < 2) { test_assert(fs_write_stream_finish(file, &output) == 0); test_assert(output == NULL); test_assert(fs_write_stream_finish_async(file) == 0); } test_file = test_fs_file_get(fs, "foo"); test_file->wait_async = FALSE; switch (i) { case 0: test_assert(fs_write_stream_finish_async(file) > 0); test_assert(test_file->contents->used > 0); break; case 1: test_file->io_failure = TRUE; test_assert(fs_write_stream_finish_async(file) < 0); test_assert(test_file->contents->used == 0); break; case 2: fs_write_stream_abort_error(file, &output, "test"); test_assert(test_file->contents->used == 0); break; } fs_file_deinit(&file); } test_end(); }
void fs_sis_try_unlink_hash_file(struct fs *sis_fs, struct fs_file *super_file) { struct fs_file *hash_file; struct stat st1, st2; const char *dir, *hash, *hash_path; if (fs_sis_path_parse(sis_fs, super_file->path, &dir, &hash) == 0 && fs_stat(super_file, &st1) == 0 && st1.st_nlink == 2) { /* this may be the last link. if hashes/ file is the same, delete it. */ hash_path = t_strdup_printf("%s/"HASH_DIR_NAME"/%s", dir, hash); hash_file = fs_file_init(super_file->fs, hash_path, FS_OPEN_MODE_READONLY); if (fs_stat(hash_file, &st2) == 0 && st1.st_ino == st2.st_ino && CMP_DEV_T(st1.st_dev, st2.st_dev)) { if (fs_delete(hash_file) < 0) i_error("%s", fs_last_error(hash_file->fs)); } fs_file_deinit(&hash_file); } }
static void test_fs_metawrap_stat(void) { struct fs *fs; struct fs_file *file; struct test_fs_file *test_file; struct istream *input; struct stat st; const char *error; unsigned int i; test_begin("fs metawrap stat"); if (fs_init("metawrap", "test", &fs_set, &fs, &error) < 0) i_fatal("fs_init() failed: %s", error); for (i = 0; i < 2; i++) { file = fs_file_init(fs, "foo", FS_OPEN_MODE_READONLY); test_file = test_fs_file_get(fs, "foo"); str_append(test_file->contents, "key:value\n\n12345678901234567890"); if (i == 0) { input = fs_read_stream(file, 2); test_istream_set_max_buffer_size(test_file->input, 2); } else { input = NULL; } test_assert_idx(fs_stat(file, &st) == 0 && st.st_size == 20, i); if (input != NULL) i_stream_unref(&input); fs_file_deinit(&file); } fs_deinit(&fs); test_end(); }