fs-sis.c revision d4c3d55021bcbf2b062f4782b1cde9115d35aefc
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2010-2012 Dovecot authors, see the included COPYING file */
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen#include "lib.h"
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen#include "str.h"
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen#include "istream.h"
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen#include "ostream-cmp.h"
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen#include "fs-sis-common.h"
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstruct sis_fs {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct fs fs;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct fs *super;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen};
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstruct sis_fs_file {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct fs_file file;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct fs_file *super;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen enum fs_open_mode open_mode;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct fs_file *hash_file;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct istream *hash_input;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct ostream *fs_output;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen char *hash, *hash_path;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen};
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic void fs_sis_copy_error(struct sis_fs *fs)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_set_error(&fs->fs, "%s", fs_last_error(fs->super));
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic void fs_sis_file_copy_error(struct sis_fs_file *file)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct sis_fs *fs = (struct sis_fs *)file->file.fs;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_copy_error(fs);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainenstatic int
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainenfs_sis_init(const char *args, const struct fs_settings *set,
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen struct fs **fs_r, const char **error_r)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct sis_fs *fs;
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen const char *parent_name, *parent_args, *error;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs = i_new(struct sis_fs, 1);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs->fs = fs_class_sis;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen if (*args == '\0') {
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen *error_r = "Parent filesystem not given as parameter";
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen return -1;
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen parent_args = strchr(args, ':');
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen if (parent_args == NULL) {
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen parent_name = args;
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen parent_args = "";
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen } else {
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen parent_name = t_strdup_until(args, parent_args);
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen parent_args++;
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen }
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen if (fs_init(parent_name, parent_args, set, &fs->super, &error) < 0) {
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen *error_r = t_strdup_printf("%s: %s", parent_name, error);
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen return -1;
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen }
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen *fs_r = &fs->fs;
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen return 0;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic void fs_sis_deinit(struct fs *_fs)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct sis_fs *fs = (struct sis_fs *)_fs;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_deinit(&fs->super);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_free(fs);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic int
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenfs_sis_open(struct fs *_fs, const char *path, enum fs_open_mode mode,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen enum fs_open_flags flags, struct fs_file **file_r)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct sis_fs *fs = (struct sis_fs *)_fs;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct sis_fs_file *file;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct fs_file *super;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen const char *dir, *hash;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (mode == FS_OPEN_MODE_APPEND) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_set_error(_fs, "APPEND mode not supported");
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return -1;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (fs_open(fs->super, path, mode | flags, &super) < 0) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_copy_error(fs);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return -1;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen switch (mode) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen case FS_OPEN_MODE_RDONLY:
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen *file_r = super;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return 0;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen case FS_OPEN_MODE_CREATE:
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen case FS_OPEN_MODE_REPLACE:
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen break;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen case FS_OPEN_MODE_APPEND:
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_unreached();
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (fs_sis_path_parse(_fs, path, &dir, &hash) < 0)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return -1;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen file = i_new(struct sis_fs_file, 1);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen file->file.fs = _fs;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen file->file.path = i_strdup(fs_file_path(super));
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen file->super = super;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen file->open_mode = mode;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen file->hash = i_strdup(hash);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen /* if hashes/<hash> already exists, open it */
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen file->hash_path = i_strdup_printf("%s/"HASH_DIR_NAME"/%s", dir, hash);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (fs_open(fs->super, file->hash_path, FS_OPEN_MODE_RDONLY,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen &file->hash_file) < 0 && errno != ENOENT) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_error("fs-sis: Couldn't open hash file: %s",
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_last_error(fs->super));
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (file->hash_file != NULL) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen file->hash_input =
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_read_stream(file->hash_file, IO_BLOCK_SIZE);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen *file_r = &file->file;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return 0;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic void fs_sis_close(struct fs_file *_file)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct sis_fs_file *file = (struct sis_fs_file *)_file;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (file->hash_file != NULL) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_stream_unref(&file->hash_input);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_close(&file->hash_file);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_close(&file->super);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_free(file->hash);
66a164c358d14bb61de73288588ea65a6ba05113Timo Sirainen i_free(file->hash_path);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_free(file->file.path);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_free(file);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic ssize_t fs_sis_read(struct fs_file *_file, void *buf, size_t size)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct sis_fs_file *file = (struct sis_fs_file *)_file;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen ssize_t ret;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if ((ret = fs_read(file->super, buf, size)) < 0)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_file_copy_error(file);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return ret;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic struct istream *
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenfs_sis_read_stream(struct fs_file *_file, size_t max_buffer_size)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct sis_fs_file *file = (struct sis_fs_file *)_file;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return fs_read_stream(file->super, max_buffer_size);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic bool fs_sis_try_link(struct sis_fs_file *file)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen const char *path = fs_file_path(&file->file);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen const struct stat *st;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct stat st2;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen if (i_stream_stat(file->hash_input, FALSE, &st) < 0)
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen return FALSE;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen /* we can use the existing file */
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (fs_link(file->super->fs, file->hash_path, path) < 0) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (errno != ENOENT && errno != EMLINK)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_error("fs-sis: %s", fs_last_error(file->super->fs));
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen /* failed to use link(), continue as if it hadn't been equal */
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return FALSE;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (fs_stat(file->super->fs, path, &st2) < 0) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_error("fs-sis: %s", fs_last_error(file->super->fs));
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (fs_unlink(file->super->fs, path) < 0)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_error("fs-sis: %s", fs_last_error(file->super->fs));
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return FALSE;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (st->st_ino != st2.st_ino) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen /* the hashes/ file was already replaced with something else */
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (fs_unlink(file->super->fs, path) < 0)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_error("fs-sis: %s", fs_last_error(file->super->fs));
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return FALSE;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return TRUE;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic void fs_sis_replace_hash_file(struct sis_fs_file *file)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen const char *hash_fname, *path = fs_file_path(&file->file);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct fs *super_fs = file->super->fs;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen string_t *temp_path;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen int ret;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (file->hash_input == NULL) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen /* hash file didn't exist previously. we should be able to
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen create it with link() */
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (fs_link(super_fs, path, file->hash_path) < 0) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (errno == EEXIST) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen /* the file was just created. it's probably
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen a duplicate, but it's too much trouble
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen trying to deduplicate it anymore */
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen } else {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_error("fs-sis: %s", fs_last_error(super_fs));
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen temp_path = t_str_new(256);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen hash_fname = strrchr(file->hash_path, '/');
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (hash_fname == NULL)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen hash_fname = file->hash_path;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen else {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen str_append_n(temp_path, file->hash_path,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen (hash_fname-file->hash_path) + 1);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen hash_fname++;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen str_printfa(temp_path, "%s%s.tmp",
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen super_fs->set.temp_file_prefix, hash_fname);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen /* replace existing hash file atomically */
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen ret = fs_link(super_fs, path, str_c(temp_path));
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (ret < 0 && errno == EEXIST) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen /* either someone's racing us or it's a stale file.
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen try to continue. */
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (fs_unlink(super_fs, str_c(temp_path)) < 0 &&
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen errno != ENOENT)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_error("fs-sis: %s", fs_last_error(super_fs));
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen ret = fs_link(super_fs, path, str_c(temp_path));
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (ret < 0) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_error("fs-sis: %s", fs_last_error(super_fs));
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (fs_rename(super_fs, str_c(temp_path), file->hash_path) < 0) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (errno == ENOENT) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen /* apparently someone else just renamed it. ignore. */
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen } else {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_error("fs-sis: %s", fs_last_error(super_fs));
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen (void)fs_unlink(super_fs, str_c(temp_path));
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic int fs_sis_write(struct fs_file *_file, const void *data, size_t size)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct sis_fs_file *file = (struct sis_fs_file *)_file;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (file->hash_input != NULL &&
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen stream_cmp_block(file->hash_input, data, size) &&
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_stream_is_eof(file->hash_input)) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen /* try to use existing file */
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (fs_sis_try_link(file))
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return 0;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (fs_write(file->super, data, size) < 0) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_file_copy_error(file);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return -1;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen T_BEGIN {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_replace_hash_file(file);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen } T_END;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return 0;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic void fs_sis_write_stream(struct fs_file *_file)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct sis_fs_file *file = (struct sis_fs_file *)_file;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_assert(_file->output == NULL);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen file->fs_output = fs_write_stream(file->super);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (file->hash_input == NULL)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen _file->output = file->fs_output;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen else {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen /* compare if files are equal */
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen _file->output = o_stream_create_cmp(file->fs_output,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen file->hash_input);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic int fs_sis_write_stream_finish(struct fs_file *_file, bool success)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct sis_fs_file *file = (struct sis_fs_file *)_file;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (!success) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_write_stream_abort(file->super, &file->fs_output);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_file_copy_error(file);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return -1;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (file->hash_input != NULL &&
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen o_stream_cmp_equals(_file->output) &&
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_stream_is_eof(file->hash_input)) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (fs_sis_try_link(file)) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_write_stream_abort(file->super, &file->fs_output);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return 0;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (fs_write_stream_finish(file->super, &file->fs_output) < 0) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_file_copy_error(file);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return -1;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen T_BEGIN {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_replace_hash_file(file);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen } T_END;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return 0;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic int
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenfs_sis_lock(struct fs_file *_file, unsigned int secs, struct fs_lock **lock_r)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct sis_fs_file *file = (struct sis_fs_file *)_file;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (fs_lock(file->super, secs, lock_r) < 0) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_file_copy_error(file);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return -1;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return 0;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic void fs_sis_unlock(struct fs_lock *_lock ATTR_UNUSED)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_unreached();
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic int fs_sis_fdatasync(struct fs_file *_file)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct sis_fs_file *file = (struct sis_fs_file *)_file;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (fs_fdatasync(file->super) < 0) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_file_copy_error(file);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return -1;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return 0;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic int fs_sis_exists(struct fs *_fs, const char *path)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct sis_fs *fs = (struct sis_fs *)_fs;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (fs_exists(fs->super, path) < 0) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_copy_error(fs);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return -1;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return 0;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic int fs_sis_stat(struct fs *_fs, const char *path, struct stat *st_r)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct sis_fs *fs = (struct sis_fs *)_fs;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (fs_stat(fs->super, path, st_r) < 0) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_copy_error(fs);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return -1;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return 0;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic int fs_sis_link(struct fs *_fs, const char *src, const char *dest)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct sis_fs *fs = (struct sis_fs *)_fs;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (fs_link(fs->super, src, dest) < 0) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_copy_error(fs);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return -1;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return 0;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic int fs_sis_rename(struct fs *_fs, const char *src, const char *dest)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct sis_fs *fs = (struct sis_fs *)_fs;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (fs_rename(fs->super, src, dest) < 0) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_copy_error(fs);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return -1;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return 0;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic int fs_sis_unlink(struct fs *_fs, const char *path)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct sis_fs *fs = (struct sis_fs *)_fs;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen T_BEGIN {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_try_unlink_hash_file(&fs->fs, fs->super, path);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen } T_END;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (fs_unlink(fs->super, path) < 0) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_copy_error(fs);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return -1;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return 0;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic int fs_sis_rmdir(struct fs *_fs, const char *path)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct sis_fs *fs = (struct sis_fs *)_fs;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (fs_rmdir(fs->super, path) < 0) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_copy_error(fs);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return -1;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return 0;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstruct fs fs_class_sis = {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen .name = "sis",
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen .v = {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_init,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_deinit,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_open,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_close,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_read,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_read_stream,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_write,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_write_stream,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_write_stream_finish,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_lock,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_unlock,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_fdatasync,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_exists,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_stat,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_link,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_rename,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_unlink,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fs_sis_rmdir
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen};