file->fs->v.get_path(file);
}
+static void ATTR_FORMAT(2, 0)
+fs_set_verror(struct fs *fs, const char *fmt, va_list args)
+{
+ /* the error is always kept in the parentmost fs */
+ if (fs->parent != NULL)
+ fs_set_verror(fs->parent, fmt, args);
+ else {
+ str_truncate(fs->last_error, 0);
+ str_vprintfa(fs->last_error, fmt, args);
+ }
+}
+
const char *fs_last_error(struct fs *fs)
{
+ /* the error is always kept in the parentmost fs */
+ if (fs->parent != NULL)
+ return fs_last_error(fs->parent);
+
if (str_len(fs->last_error) == 0)
return "BUG: Unknown fs error";
return str_c(fs->last_error);
va_list args;
va_start(args, fmt);
- str_truncate(fs->last_error, 0);
- str_vprintfa(fs->last_error, fmt, args);
+ fs_set_verror(fs, fmt, args);
va_end(args);
}
va_list args;
va_start(args, fmt);
- str_truncate(fs->last_error, 0);
- str_vprintfa(fs->last_error, fmt, args);
- i_error("fs-%s: %s", fs->name, str_c(fs->last_error));
+ fs_set_verror(fs, fmt, args);
+
+ i_error("fs-%s: %s", fs->name, fs_last_error(fs));
va_end(args);
}
struct metawrap_fs {
struct fs fs;
- struct fs *super;
bool wrap_metadata;
};
bool metadata_read;
};
-static void fs_metawrap_copy_error(struct metawrap_fs *fs)
-{
- fs_set_error(&fs->fs, "%s", fs_last_error(fs->super));
-}
-
-static void fs_metawrap_file_copy_error(struct metawrap_fs_file *file)
-{
- struct metawrap_fs *fs = (struct metawrap_fs *)file->file.fs;
-
- fs_metawrap_copy_error(fs);
-}
-
static struct fs *fs_metawrap_alloc(void)
{
struct metawrap_fs *fs;
parent_name = t_strdup_until(args, parent_args);
parent_args++;
}
- if (fs_init(parent_name, parent_args, set, &fs->super, &error) < 0) {
+ if (fs_init(parent_name, parent_args, set, &_fs->parent, &error) < 0) {
fs_set_error(_fs, "%s: %s", parent_name, error);
return -1;
}
- if ((fs_get_properties(fs->super) & FS_PROPERTY_METADATA) == 0)
+ if ((fs_get_properties(_fs->parent) & FS_PROPERTY_METADATA) == 0)
fs->wrap_metadata = TRUE;
return 0;
}
{
struct metawrap_fs *fs = (struct metawrap_fs *)_fs;
- if (fs->super != NULL)
- fs_deinit(&fs->super);
+ if (_fs->parent != NULL)
+ fs_deinit(&_fs->parent);
i_free(fs);
}
const struct metawrap_fs *fs = (const struct metawrap_fs *)_fs;
enum fs_properties props;
- props = fs_get_properties(fs->super);
+ props = fs_get_properties(_fs->parent);
if (fs->wrap_metadata) {
/* we don't have a quick stat() to see the file's size,
because of the metadata header */
/* avoid unnecessarily creating two seekable streams */
flags &= ~FS_OPEN_FLAG_SEEKABLE;
- file->super = fs_file_init(fs->super, path, mode | flags);
+ file->super = fs_file_init(_fs->parent, path, mode | flags);
if (file->fs->wrap_metadata && mode == FS_OPEN_MODE_READONLY &&
(flags & FS_OPEN_FLAG_ASYNC) == 0) {
/* use async stream for super, so fs_read_stream() won't create
another seekable stream unneededly */
- file->super_read = fs_file_init(fs->super, path, mode | flags |
+ file->super_read = fs_file_init(_fs->parent, path, mode | flags |
FS_OPEN_FLAG_ASYNC);
} else {
file->super_read = file->super;
static int fs_metawrap_wait_async(struct fs *_fs)
{
- struct metawrap_fs *fs = (struct metawrap_fs *)_fs;
-
- if (fs_wait_async(fs->super) < 0) {
- fs_metawrap_copy_error(fs);
- return -1;
- }
- return 0;
+ return fs_wait_async(_fs->parent);
}
static void
struct metawrap_fs_file *file = (struct metawrap_fs_file *)_file;
char c;
- if (!file->fs->wrap_metadata) {
- if (fs_get_metadata(file->super, metadata_r) < 0) {
- fs_metawrap_file_copy_error(file);
- return -1;
- }
- return 0;
- }
+ if (!file->fs->wrap_metadata)
+ return fs_get_metadata(file->super, metadata_r);
if (!file->metadata_read) {
if (fs_read(_file, &c, 1) < 0)
static ssize_t fs_metawrap_read(struct fs_file *_file, void *buf, size_t size)
{
struct metawrap_fs_file *file = (struct metawrap_fs_file *)_file;
- ssize_t ret;
- if (!file->fs->wrap_metadata) {
- if ((ret = fs_read(file->super, buf, size)) < 0)
- fs_metawrap_file_copy_error(file);
- return ret;
- }
+ if (!file->fs->wrap_metadata)
+ return fs_read(file->super, buf, size);
return fs_read_via_stream(_file, buf, size);
}
{
struct metawrap_fs_file *file = (struct metawrap_fs_file *)_file;
- if (!file->fs->wrap_metadata) {
- if (fs_write(file->super, data, size) < 0) {
- fs_metawrap_file_copy_error(file);
- return -1;
- }
- return 0;
- }
+ if (!file->fs->wrap_metadata)
+ return fs_write(file->super, data, size);
return fs_write_via_stream(_file, data, size);
}
} else {
ret = fs_write_stream_finish(file->super, &file->super_output);
}
-
- if (ret < 0)
- fs_metawrap_file_copy_error(file);
return ret;
}
{
struct metawrap_fs_file *file = (struct metawrap_fs_file *)_file;
- if (fs_lock(file->super, secs, lock_r) < 0) {
- fs_metawrap_file_copy_error(file);
- return -1;
- }
- return 0;
+ return fs_lock(file->super, secs, lock_r);
}
static void fs_metawrap_unlock(struct fs_lock *_lock ATTR_UNUSED)
{
struct metawrap_fs_file *file = (struct metawrap_fs_file *)_file;
- if (fs_exists(file->super) < 0) {
- fs_metawrap_copy_error(file->fs);
- return -1;
- }
- return 0;
+ return fs_exists(file->super);
}
static int fs_metawrap_stat(struct fs_file *_file, struct stat *st_r)
uoff_t input_size;
ssize_t ret;
- if (!file->fs->wrap_metadata) {
- if (fs_stat(file->super, st_r) < 0) {
- fs_metawrap_copy_error(file->fs);
- return -1;
- }
- return 0;
- }
+ if (!file->fs->wrap_metadata)
+ return fs_stat(file->super, st_r);
input = fs_read_stream(_file, IO_BLOCK_SIZE);
if ((ret = i_stream_get_size(input, TRUE, &input_size)) < 0) {
fs_set_error(_file->fs, "i_stream_get_size(%s) failed: %m",
if (fs_stat(file->super, st_r) < 0) {
i_assert(errno != EAGAIN); /* read should have caught this */
- fs_metawrap_copy_error(file->fs);
return -1;
}
st_r->st_size = input_size;
struct metawrap_fs_file *src = (struct metawrap_fs_file *)_src;
struct metawrap_fs_file *dest = (struct metawrap_fs_file *)_dest;
- if (!dest->fs->wrap_metadata) {
- if (fs_copy(src->super, dest->super) < 0) {
- fs_metawrap_copy_error(src->fs);
- return -1;
- }
- return 0;
- }
+ if (!dest->fs->wrap_metadata)
+ return fs_copy(src->super, dest->super);
return fs_default_copy(_src, _dest);
}
struct metawrap_fs_file *src = (struct metawrap_fs_file *)_src;
struct metawrap_fs_file *dest = (struct metawrap_fs_file *)_dest;
- if (fs_rename(src->super, dest->super) < 0) {
- fs_metawrap_copy_error(src->fs);
- return -1;
- }
- return 0;
+ return fs_rename(src->super, dest->super);
}
static int fs_metawrap_delete(struct fs_file *_file)
{
struct metawrap_fs_file *file = (struct metawrap_fs_file *)_file;
- if (fs_delete(file->super) < 0) {
- fs_metawrap_copy_error(file->fs);
- return -1;
- }
- return 0;
+ return fs_delete(file->super);
}
static struct fs_iter *
fs_metawrap_iter_init(struct fs *_fs, const char *path,
enum fs_iter_flags flags)
{
- struct metawrap_fs *fs = (struct metawrap_fs *)_fs;
-
- return fs_iter_init(fs->super, path, flags);
+ return fs_iter_init(_fs->parent, path, flags);
}
const struct fs fs_class_metawrap = {