]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-fs: Add errno parameter to fs_set_error() change callers to use it.
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 21 Jan 2020 13:59:51 +0000 (15:59 +0200)
committerJosef 'Jeff' Sipek <jeff.sipek@dovecot.fi>
Wed, 22 Jan 2020 18:40:17 +0000 (13:40 -0500)
This is now explicit so it can't be forgotten accidentally. Fixes several
bugs where errno wasn't set on error conditions, which could have caused
callers to handle the error wrong.

src/lib-fs/fs-api-private.h
src/lib-fs/fs-api.c
src/lib-fs/fs-dict.c
src/lib-fs/fs-metawrap.c
src/lib-fs/fs-posix.c
src/lib-fs/fs-randomfail.c
src/lib-fs/fs-sis-common.c
src/lib-fs/fs-sis-queue.c
src/lib-fs/fs-sis.c

index 28394bc37af4ceb149476fcafcc17d9420745e6d..395e3f3ff48321972b03dc129129b4d8bbb36e84 100644 (file)
@@ -168,8 +168,10 @@ extern const struct fs fs_class_test;
 
 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);
 
index 3ba76c6d222ce15b0f960dc9932d87a04105cac6..8bdfa0fd4a313a5172123497c7164685864a7c8c 100644 (file)
@@ -490,7 +490,7 @@ int fs_get_metadata(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 &&
@@ -645,7 +645,9 @@ ssize_t fs_read_via_stream(struct fs_file *file, void *buf, size_t size)
                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 {
@@ -859,7 +861,8 @@ int fs_write_stream_finish(struct fs_file *file, struct ostream **output)
                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;
@@ -1006,7 +1009,7 @@ int fs_stat(struct fs_file *file, struct stat *st_r)
        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;
        }
 
@@ -1112,7 +1115,7 @@ int fs_copy(struct fs_file *src, struct fs_file *dest)
        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;
        }
 
@@ -1232,7 +1235,7 @@ int fs_iter_deinit(struct fs_iter **_iter, const char **error_r)
        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);
@@ -1284,10 +1287,13 @@ const struct fs_stats *fs_get_stats(struct fs *fs)
        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);
@@ -1306,8 +1312,7 @@ void fs_set_error_errno(struct event *event, const char *fmt, ...)
 
 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
index 1cb635387d6732c7f88f40bcd5919a55d6914569..4e1398a3e53ffac2e104065ab211b36830accd72 100644 (file)
@@ -160,12 +160,12 @@ static int fs_dict_lookup(struct dict_fs_file *file)
        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;
        }
 }
@@ -243,8 +243,8 @@ static int fs_dict_write_stream_finish(struct fs_file *_file, bool success)
        }
        }
        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;
@@ -272,8 +272,8 @@ static int fs_dict_delete(struct fs_file *_file)
        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;
@@ -316,7 +316,8 @@ static int fs_dict_iter_deinit(struct fs_iter *_iter)
 
        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;
 }
 
index 37fb9af80c7af70df015dce13529c26101df608c..55e227592ee38c2752c110576d5cd47e7b96b8b2 100644 (file)
@@ -188,7 +188,8 @@ fs_metawrap_get_metadata(struct fs_file *_file,
                        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;
@@ -433,7 +434,7 @@ static int fs_metawrap_stat(struct fs_file *_file, struct stat *st_r)
                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,
@@ -451,7 +452,8 @@ static int fs_metawrap_stat(struct fs_file *_file, struct stat *st_r)
                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;
@@ -459,9 +461,8 @@ static int fs_metawrap_stat(struct fs_file *_file, struct stat *st_r)
        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;
        }
 
index 56b24479f1cb1281eb1231132fe477a4954cd745..c5aacf384ab6f93047dc4648e2b47bc0d73f0d86 100644 (file)
@@ -623,10 +623,9 @@ static int fs_posix_write(struct fs_file *_file, const void *data, size_t size)
                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;
@@ -697,8 +696,9 @@ fs_posix_lock(struct fs_file *_file, unsigned int secs, struct fs_lock **lock_r)
        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,
index 182992d7e0b1974c7e0385ca5312ca7761cef390..8a3d696de7f2fc38517ded5e8196c678e18236c1 100644 (file)
@@ -240,8 +240,7 @@ static bool fs_random_fail(struct fs *_fs, struct event *event,
        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;
@@ -506,8 +505,7 @@ static int fs_randomfail_iter_deinit(struct fs_iter *_iter)
        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;
index f516ac3ce0148e660bd14cf6b4f211a144f92b3c..654c44ec56757ed9305de0717d02c6128aadda19 100644 (file)
@@ -22,7 +22,7 @@ int fs_sis_path_parse(struct fs_file *file, const char *path,
        /* 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;
        }
index f5f894d8b992f77e0d36939fa6fd8f9e5fba3bb8..35ac314162ff0ad442e05221da3b0792d11fadb7 100644 (file)
@@ -81,7 +81,7 @@ fs_sis_queue_file_init(struct fs_file *_file, const char *path,
        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);
 }
index c0979aa8e5aac2976d95ef2597015a984a23dd55..0d3d1cd5d414277142691cbcbe299199af5f7d1c 100644 (file)
@@ -93,7 +93,7 @@ fs_sis_file_init(struct fs_file *_file, const char *path,
        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;
        }