예제 #1
0
static int
fs_sis_init(struct fs *_fs, const char *args, const struct fs_settings *set)
{
	enum fs_properties props;
	const char *parent_name, *parent_args, *error;

	if (*args == '\0') {
		fs_set_error(_fs, "Parent filesystem not given as parameter");
		return -1;
	}

	parent_args = strchr(args, ':');
	if (parent_args == NULL) {
		parent_name = args;
		parent_args = "";
	} else {
		parent_name = t_strdup_until(args, parent_args);
		parent_args++;
	}
	if (fs_init(parent_name, parent_args, set, &_fs->parent, &error) < 0) {
		fs_set_error(_fs, "%s", error);
		return -1;
	}
	props = fs_get_properties(_fs->parent);
	if ((props & FS_SIS_REQUIRED_PROPS) != FS_SIS_REQUIRED_PROPS) {
		fs_set_error(_fs, "%s backend can't be used with SIS",
			     parent_name);
		return -1;
	}
	return 0;
}
예제 #2
0
static int
fs_sis_queue_init(struct fs *_fs, const char *args,
		  const struct fs_settings *set)
{
	struct sis_queue_fs *fs = (struct sis_queue_fs *)_fs;
	const char *p, *parent_name, *parent_args, *error;

	/* <queue_dir>:<parent fs>[:<args>] */

	p = strchr(args, ':');
	if (p == NULL || p[1] == '\0') {
		fs_set_error(_fs, "Parent filesystem not given as parameter");
		return -1;
	}

	fs->queue_dir = i_strdup_until(args, p);
	parent_name = p + 1;

	parent_args = strchr(parent_name, ':');
	if (parent_args == NULL)
		parent_args = "";
	else
		parent_name = t_strdup_until(parent_name, parent_args++);
	if (fs_init(parent_name, parent_args, set, &fs->super, &error) < 0) {
		fs_set_error(_fs, "%s: %s", parent_name, error);
		return -1;
	}
	return 0;
}
예제 #3
0
static int
fs_compress_init(struct fs *_fs, const char *args, const
		 struct fs_settings *set)
{
	struct compress_fs *fs = (struct compress_fs *)_fs;
	const char *p, *compression_name, *level_str, *error;
	const char *parent_name, *parent_args;

	/* get compression handler name */
	p = strchr(args, ':');
	if (p == NULL) {
		fs_set_error(_fs, "Compression method not given as parameter");
		return -1;
	}
	compression_name = t_strdup_until(args, p++);
	args = p;

	/* get compression level */
	p = strchr(args, ':');
	if (p == NULL || p[1] == '\0') {
		fs_set_error(_fs, "Parent filesystem not given as parameter");
		return -1;
	}

	level_str = t_strdup_until(args, p++);
	if (str_to_uint(level_str, &fs->compress_level) < 0 ||
	    fs->compress_level < 1 || fs->compress_level > 9) {
		fs_set_error(_fs, "Invalid compression level parameter '%s'", level_str);
		return -1;
	}
	args = p;

	fs->handler = compression_lookup_handler(compression_name);
	if (fs->handler == NULL) {
		fs_set_error(_fs, "Compression method '%s' not support", compression_name);
		return -1;
	}

	parent_args = strchr(args, ':');
	if (parent_args == NULL) {
		parent_name = args;
		parent_args = "";
	} else {
		parent_name = t_strdup_until(args, parent_args);
		parent_args++;
	}
	if (fs_init(parent_name, parent_args, set, &_fs->parent, &error) < 0) {
		fs_set_error(_fs, "%s: %s", parent_name, error);
		return -1;
	}
	return 0;
}
예제 #4
0
static int
fs_sis_open(struct fs *_fs, const char *path, enum fs_open_mode mode,
	    enum fs_open_flags flags, struct fs_file **file_r)
{
	struct sis_fs *fs = (struct sis_fs *)_fs;
	struct sis_fs_file *file;
	struct fs_file *super;
	const char *dir, *hash;

	if (mode == FS_OPEN_MODE_APPEND) {
		fs_set_error(_fs, "APPEND mode not supported");
		return -1;
	}

	if (fs_open(fs->super, path, mode | flags, &super) < 0) {
		fs_sis_copy_error(fs);
		return -1;
	}

	switch (mode) {
	case FS_OPEN_MODE_RDONLY:
		*file_r = super;
		return 0;
	case FS_OPEN_MODE_CREATE:
	case FS_OPEN_MODE_REPLACE:
		break;
	case FS_OPEN_MODE_APPEND:
		i_unreached();
	}

	if (fs_sis_path_parse(_fs, path, &dir, &hash) < 0)
		return -1;

	file = i_new(struct sis_fs_file, 1);
	file->file.fs = _fs;
	file->file.path = i_strdup(fs_file_path(super));
	file->super = super;
	file->open_mode = mode;
	file->hash = i_strdup(hash);

	/* if hashes/<hash> already exists, open it */
	file->hash_path = i_strdup_printf("%s/"HASH_DIR_NAME"/%s", dir, hash);
	if (fs_open(fs->super, file->hash_path, FS_OPEN_MODE_RDONLY,
		    &file->hash_file) < 0 && errno != ENOENT) {
		i_error("fs-sis: Couldn't open hash file: %s",
			fs_last_error(fs->super));
	}
	if (file->hash_file != NULL) {
		file->hash_input =
			fs_read_stream(file->hash_file, IO_BLOCK_SIZE);
	}

	*file_r = &file->file;
	return 0;
}
예제 #5
0
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;
}
예제 #6
0
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;
}
int fs_sis_path_parse(struct fs *fs, const char *path,
		      const char **dir_r, const char **hash_r)
{
	const char *fname, *p;

	fname = strrchr(path, '/');
	if (fname == NULL) {
		*dir_r = ".";
		fname = path;
	} else {
		*dir_r = t_strdup_until(path, fname);
		fname++;
	}

	/* assume filename begins with "<hash>-" */
	p = strchr(fname, '-');
	if (p == NULL) {
		fs_set_error(fs, "open(%s) failed: "
			     "Filenames must begin with '<hash>-'", path);
		return -1;
	}
	*hash_r = t_strdup_until(fname, p);
	return 0;
}
예제 #8
0
static void fs_sis_queue_copy_error(struct sis_queue_fs *fs)
{
	fs_set_error(&fs->fs, "%s", fs_last_error(fs->super));
}
예제 #9
0
static void fs_sis_copy_error(struct sis_fs *fs)
{
	fs_set_error(&fs->fs, "%s", fs_last_error(fs->fs.parent));
}
예제 #10
0
static int
fs_crypt_init(struct fs *_fs, const char *args, const
	      struct fs_settings *set)
{
	struct crypt_fs *fs = (struct crypt_fs *)_fs;
	const char *enc_algo, *set_prefix;
	const char *p, *arg, *value, *error, *parent_name, *parent_args;
	const char *public_key_path = "", *private_key_path = "", *password = "";

	random_init();
	if (!dcrypt_initialize("openssl", NULL, &error))
		i_fatal("dcrypt_initialize(): %s", error);

	/* [algo=<s>:][set_prefix=<n>:][public_key_path=<s>:]
	   [private_key_path=<s>:[password=<s>:]]<parent fs> */
	set_prefix = "mail_crypt_global";
	enc_algo = "aes-256-gcm-sha256";
	for (;;) {
		p = strchr(args, ':');
		if (p == NULL) {
			fs_set_error(_fs, "Missing parameters");
			return -1;
		}
		arg = t_strdup_until(args, p);
		if ((value = strchr(arg, '=')) == NULL)
			break;
		arg = t_strdup_until(arg, value++);
		args = p+1;

		if (strcmp(arg, "algo") == 0)
			enc_algo = value;
		else if (strcmp(arg, "set_prefix") == 0)
			set_prefix = value;
		else if (strcmp(arg, "public_key_path") == 0)
			public_key_path = value;
		else if (strcmp(arg, "private_key_path") == 0)
			private_key_path = value;
		else if (strcmp(arg, "password") == 0)
			password = value;
		else {
			fs_set_error(_fs, "Invalid parameter '%s'", arg);
			return -1;
		}
	}

	parent_args = strchr(args, ':');
	if (parent_args == NULL) {
		parent_name = args;
		parent_args = "";
	} else {
		parent_name = t_strdup_until(args, parent_args);
		parent_args++;
	}
	if (fs_init(parent_name, parent_args, set, &_fs->parent, &error) < 0) {
		fs_set_error(_fs, "%s: %s", parent_name, error);
		return -1;
	}
	fs->enc_algo = i_strdup(enc_algo);
	fs->set_prefix = i_strdup(set_prefix);
	fs->public_key_path = i_strdup_empty(public_key_path);
	fs->private_key_path = i_strdup_empty(private_key_path);
	fs->password = i_strdup_empty(password);
	return 0;
}