void fs_class_register(const struct fs *fs_class);
-/* Event must be fs_file or fs_iter events */
-void fs_set_error(struct event *event, const char *fmt, ...) ATTR_FORMAT(2, 3);
+/* Event must be fs_file or fs_iter events. Set errno from err. */
+void fs_set_error(struct event *event, int err,
+ const char *fmt, ...) ATTR_FORMAT(3, 4);
+/* Like fs_set_error(), but use the existing errno. */
void fs_set_error_errno(struct event *event, const char *fmt, ...) ATTR_FORMAT(2, 3);
void fs_file_set_error_async(struct fs_file *file);
*metadata_r = &file->metadata;
return 0;
}
- fs_set_error(file->event, "Metadata not supported by backend");
+ fs_set_error(file->event, ENOTSUP, "Metadata not supported by backend");
return -1;
}
if (!file->read_or_prefetch_counted &&
return -1;
}
if (ret < 0 && file->pending_read_input->stream_errno != 0) {
- fs_set_error(file->event, "read(%s) failed: %s",
+ fs_set_error(file->event,
+ file->pending_read_input->stream_errno,
+ "read(%s) failed: %s",
i_stream_get_name(file->pending_read_input),
i_stream_get_error(file->pending_read_input));
} else {
o_stream_uncork(file->output);
if ((ret = o_stream_finish(file->output)) <= 0) {
i_assert(ret < 0);
- fs_set_error(file->event, "write(%s) failed: %s",
+ fs_set_error(file->event, file->output->stream_errno,
+ "write(%s) failed: %s",
o_stream_get_name(file->output),
o_stream_get_error(file->output));
success = FALSE;
int ret;
if (file->fs->v.stat == NULL) {
- fs_set_error(file->event, "fs_stat() not supported");
+ fs_set_error(file->event, ENOTSUP, "fs_stat() not supported");
return -1;
}
i_assert(src->fs == dest->fs);
if (src->fs->v.copy == NULL) {
- fs_set_error(src->event, "fs_copy() not supported");
+ fs_set_error(src->event, ENOTSUP, "fs_copy() not supported");
return -1;
}
DLLIST_REMOVE(&fs->iters, iter);
if (fs->v.iter_deinit == NULL) {
- fs_set_error(event, "FS iteration not supported");
+ fs_set_error(event, ENOTSUP, "FS iteration not supported");
ret = -1;
} else T_BEGIN {
ret = iter->fs->v.iter_deinit(iter);
return &fs->stats;
}
-void fs_set_error(struct event *event, const char *fmt, ...)
+void fs_set_error(struct event *event, int err, const char *fmt, ...)
{
va_list args;
+ i_assert(err != 0);
+
+ errno = err;
va_start(args, fmt);
fs_set_verror(event, fmt, args);
va_end(args);
void fs_file_set_error_async(struct fs_file *file)
{
- errno = EAGAIN;
- fs_set_error(file->event, "Asynchronous operation in progress");
+ fs_set_error(file->event, EAGAIN, "Asynchronous operation in progress");
}
static uint64_t
if (ret > 0)
return 0;
else if (ret < 0) {
- errno = EIO;
- fs_set_error(file->file.event, "dict_lookup(%s) failed: %s", file->key, error);
+ fs_set_error(file->file.event, EIO,
+ "dict_lookup(%s) failed: %s", file->key, error);
return -1;
} else {
- errno = ENOENT;
- fs_set_error(file->file.event, "Dict key %s doesn't exist", file->key);
+ fs_set_error(file->file.event, ENOENT,
+ "Dict key %s doesn't exist", file->key);
return -1;
}
}
}
}
if (dict_transaction_commit(&trans, &error) < 0) {
- errno = EIO;
- fs_set_error(_file->event, "Dict transaction commit failed: %s", error);
+ fs_set_error(_file->event, EIO,
+ "Dict transaction commit failed: %s", error);
return -1;
}
return 1;
trans = dict_transaction_begin(fs->dict);
dict_unset(trans, file->key);
if (dict_transaction_commit(&trans, &error) < 0) {
- errno = EIO;
- fs_set_error(_file->event, "Dict transaction commit failed: %s", error);
+ fs_set_error(_file->event, EIO,
+ "Dict transaction commit failed: %s", error);
return -1;
}
return 0;
ret = dict_iterate_deinit(&iter->dict_iter, &error);
if (ret < 0)
- fs_set_error(_iter->event, "Dict iteration failed: %s", error);
+ fs_set_error(_iter->event, EIO,
+ "Dict iteration failed: %s", error);
return ret;
}
fs_wait_async(_file->fs);
}
if (ret == -1 && file->input->stream_errno != 0) {
- fs_set_error(_file->event, "read(%s) failed: %s",
+ fs_set_error(_file->event, file->input->stream_errno,
+ "read(%s) failed: %s",
i_stream_get_name(file->input),
i_stream_get_error(file->input));
return -1;
if (fs_stat(_file->parent, st_r) < 0)
return -1;
if ((uoff_t)st_r->st_size < file->metadata_write_size) {
- fs_set_error(_file->event,
+ fs_set_error(_file->event, EIO,
"Just-written %s shrank unexpectedly "
"(%"PRIuUOFF_T" < %"PRIuUOFF_T")",
fs_file_path(_file), st_r->st_size,
i_stream_ref(input);
}
if ((ret = i_stream_get_size(input, TRUE, &input_size)) < 0) {
- fs_set_error(_file->event, "i_stream_get_size(%s) failed: %s",
+ fs_set_error(_file->event, input->stream_errno,
+ "i_stream_get_size(%s) failed: %s",
fs_file_path(_file), i_stream_get_error(input));
i_stream_unref(&input);
return -1;
i_stream_unref(&input);
if (ret == 0) {
/* we shouldn't get here */
- fs_set_error(_file->event, "i_stream_get_size(%s) returned size as unknown",
+ fs_set_error(_file->event, EIO, "i_stream_get_size(%s) returned size as unknown",
fs_file_path(_file));
- errno = EIO;
return -1;
}
return -1;
}
if ((size_t)ret != size) {
- fs_set_error(_file->event,
+ fs_set_error(_file->event, ENOSPC,
"write(%s) returned %"PRIuSIZE_T"/%"PRIuSIZE_T,
file->full_path, (size_t)ret, size);
- errno = ENOSPC;
return -1;
}
return 0;
switch (fs->lock_method) {
case FS_POSIX_LOCK_METHOD_FLOCK:
#ifndef HAVE_FLOCK
- fs_set_error(_file->event, "flock() not supported by OS "
- "(for file %s)", file->full_path);
+ fs_set_error(_file->event, ENOTSUP,
+ "flock() not supported by OS (for file %s)",
+ file->full_path);
#else
if (secs == 0) {
ret = file_try_lock(file->fd, file->full_path, F_WRLCK,
if (fs->op_probability[op] == 0)
return FALSE;
if ((unsigned int)i_rand_limit(100 * divider) <= fs->op_probability[op]) {
- errno = EIO;
- fs_set_error(event, RANDOMFAIL_ERROR);
+ fs_set_error(event, EIO, RANDOMFAIL_ERROR);
return TRUE;
}
return FALSE;
if ((ret = fs_iter_deinit(&iter->super, &error)) < 0)
fs_set_error_errno(_iter->event, "%s", error);
if (iter->fail_pos == 1) {
- fs_set_error(_iter->event, RANDOMFAIL_ERROR);
- errno = EIO;
+ fs_set_error(_iter->event, EIO, RANDOMFAIL_ERROR);
ret = -1;
}
return ret;
/* assume filename begins with "<hash>-" */
p = strchr(fname, '-');
if (p == NULL) {
- fs_set_error(file->event, "open(%s) failed: "
+ fs_set_error(file->event, EINVAL, "open(%s) failed: "
"Filenames must begin with '<hash>-'", path);
return -1;
}
file->fs = fs;
if (mode == FS_OPEN_MODE_APPEND)
- fs_set_error(_file->event, "APPEND mode not supported");
+ fs_set_error(_file->event, ENOTSUP, "APPEND mode not supported");
else
file->file.parent = fs_file_init_parent(_file, path, mode | flags);
}
file->fs = fs;
file->open_mode = mode;
if (mode == FS_OPEN_MODE_APPEND) {
- fs_set_error(_file->event, "APPEND mode not supported");
+ fs_set_error(_file->event, ENOTSUP, "APPEND mode not supported");
return;
}