From: Aki Tuomi Date: Fri, 19 Aug 2016 13:00:30 +0000 (+0300) Subject: fs-api: Add and use fs_write_stream_abort_error X-Git-Tag: 2.3.0.rc1~3114 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=be6fab2b1eded6b57d6688c6aa5a7c784f943865;p=thirdparty%2Fdovecot%2Fcore.git fs-api: Add and use fs_write_stream_abort_error This lets caller to specify error instead of setting it with fs_error. Doing it like this lets us percolate the error upwards. --- diff --git a/src/lib-fs/fs-api.c b/src/lib-fs/fs-api.c index e53059348c..15dc85d233 100644 --- a/src/lib-fs/fs-api.c +++ b/src/lib-fs/fs-api.c @@ -276,7 +276,7 @@ void fs_file_close(struct fs_file *file) if (file->copy_input != NULL) { i_stream_unref(&file->copy_input); - (void)fs_write_stream_abort(file, &file->copy_output); + fs_write_stream_abort(file, &file->copy_output); } i_free_and_null(file->write_digest); if (file->fs->v.file_close != NULL) T_BEGIN { @@ -610,10 +610,9 @@ int fs_write_via_stream(struct fs_file *file, const void *data, size_t size) output = fs_write_stream(file); if ((ret = o_stream_send(output, data, size)) < 0) { err = errno; - fs_set_error(file->fs, "fs_write(%s) failed: %s", - o_stream_get_name(output), - o_stream_get_error(output)); - fs_write_stream_abort(file, &output); + fs_write_stream_abort_error(file, &output, "fs_write(%s) failed: %s", + o_stream_get_name(output), + o_stream_get_error(output)); errno = err; return -1; } @@ -719,9 +718,11 @@ int fs_write_stream_finish_async(struct fs_file *file) return fs_write_stream_finish_int(file, TRUE); } -void fs_write_stream_abort(struct fs_file *file, struct ostream **output) +void fs_write_stream_abort_error(struct fs_file *file, struct ostream **output, const char *error_fmt, ...) { int ret; + va_list args; + va_start(args, error_fmt); i_assert(*output == file->output); i_assert(file->output != NULL); @@ -730,9 +731,16 @@ void fs_write_stream_abort(struct fs_file *file, struct ostream **output) *output = NULL; o_stream_ignore_last_errors(file->output); /* make sure we don't have an old error lying around */ - fs_set_error(file->fs, "Write aborted"); + fs_set_verror(file->fs, error_fmt, args); ret = fs_write_stream_finish_int(file, FALSE); i_assert(ret != 0); + + va_end(args); +} + +void fs_write_stream_abort(struct fs_file *file, struct ostream **output) +{ + fs_write_stream_abort_error(file, output, "Write aborted"); } void fs_write_set_hash(struct fs_file *file, const struct hash_method *method, @@ -904,19 +912,19 @@ int fs_default_copy(struct fs_file *src, struct fs_file *dest) return -1; case OSTREAM_SEND_ISTREAM_RESULT_ERROR_INPUT: errno = dest->copy_input->stream_errno; - fs_set_error(dest->fs, "read(%s) failed: %s", - i_stream_get_name(dest->copy_input), - i_stream_get_error(dest->copy_input)); + fs_write_stream_abort_error(dest, &dest->copy_output, + "read(%s) failed: %s", + i_stream_get_name(dest->copy_input), + i_stream_get_error(dest->copy_input)); i_stream_unref(&dest->copy_input); - fs_write_stream_abort(dest, &dest->copy_output); return -1; case OSTREAM_SEND_ISTREAM_RESULT_ERROR_OUTPUT: errno = dest->copy_output->stream_errno; - fs_set_error(dest->fs, "write(%s) failed: %s", - o_stream_get_name(dest->copy_output), - o_stream_get_error(dest->copy_output)); + fs_write_stream_abort_error(dest, &dest->copy_output, + "write(%s) failed: %s", + o_stream_get_name(dest->copy_output), + o_stream_get_error(dest->copy_output)); i_stream_unref(&dest->copy_input); - fs_write_stream_abort(dest, &dest->copy_output); return -1; } i_stream_unref(&dest->copy_input); diff --git a/src/lib-fs/fs-api.h b/src/lib-fs/fs-api.h index cf285b1716..1ef7b478a4 100644 --- a/src/lib-fs/fs-api.h +++ b/src/lib-fs/fs-api.h @@ -275,6 +275,7 @@ int fs_write_stream_finish_async(struct fs_file *file); fs_write_stream_finish(), i.e. it can't be used to abort a pending async write. */ void fs_write_stream_abort(struct fs_file *file, struct ostream **output); +void fs_write_stream_abort_error(struct fs_file *file, struct ostream **output, const char *error_fmt, ...) ATTR_FORMAT(3, 4); /* Set a hash to the following write. The storage can then verify that the input data matches the specified hash, or fail if it doesn't. Typically diff --git a/src/lib-fs/fs-metawrap.c b/src/lib-fs/fs-metawrap.c index 4b5627737e..663adad883 100644 --- a/src/lib-fs/fs-metawrap.c +++ b/src/lib-fs/fs-metawrap.c @@ -364,7 +364,9 @@ static int fs_metawrap_write_stream_finish(struct fs_file *_file, bool success) if (file->super_output != NULL) { /* no metawrap */ i_assert(file->temp_output == NULL); - fs_write_stream_abort(_file->parent, &file->super_output); + fs_write_stream_abort_error(_file->parent, &file->super_output, "error(%s): %s", + o_stream_get_name(file->super_output), + o_stream_get_error(file->super_output)); } else { i_assert(file->temp_output != NULL); o_stream_destroy(&file->temp_output); diff --git a/src/lib-fs/fs-randomfail.c b/src/lib-fs/fs-randomfail.c index 484a12328b..a1593290e6 100644 --- a/src/lib-fs/fs-randomfail.c +++ b/src/lib-fs/fs-randomfail.c @@ -402,7 +402,7 @@ static int fs_randomfail_write_stream_finish(struct fs_file *_file, bool success else o_stream_unref(&_file->output); if (!success || fs_random_fail(_file->fs, 1, FS_OP_WRITE)) { - fs_write_stream_abort(file->super, &file->super_output); + fs_write_stream_abort_error(file->super, &file->super_output, RANDOMFAIL_ERROR); return -1; } } diff --git a/src/lib-fs/fs-sis-queue.c b/src/lib-fs/fs-sis-queue.c index 1e38d643db..3936933355 100644 --- a/src/lib-fs/fs-sis-queue.c +++ b/src/lib-fs/fs-sis-queue.c @@ -149,7 +149,10 @@ static int fs_sis_queue_write_stream_finish(struct fs_file *_file, bool success) if (!success) { if (_file->parent != NULL) - fs_write_stream_abort(_file->parent, &_file->output); + fs_write_stream_abort_error(_file->parent, &_file->output, + "write(%s) failed: %s", + o_stream_get_name(_file->output), + o_stream_get_error(_file->output)); return -1; } diff --git a/src/lib-fs/fs-sis.c b/src/lib-fs/fs-sis.c index eb947c101f..d36daf5012 100644 --- a/src/lib-fs/fs-sis.c +++ b/src/lib-fs/fs-sis.c @@ -287,7 +287,10 @@ static int fs_sis_write_stream_finish(struct fs_file *_file, bool success) if (!success) { if (_file->parent != NULL) - fs_write_stream_abort(_file->parent, &file->fs_output); + fs_write_stream_abort_error(_file->parent, &file->fs_output, + "write(%s) error: %s", + o_stream_get_name(file->fs_output), + o_stream_get_error(file->fs_output)); o_stream_unref(&_file->output); return -1; } diff --git a/src/lib-fs/fs-wrapper.c b/src/lib-fs/fs-wrapper.c index 524f113131..85c194b99e 100644 --- a/src/lib-fs/fs-wrapper.c +++ b/src/lib-fs/fs-wrapper.c @@ -2,6 +2,7 @@ #include "lib.h" #include "fs-api-private.h" +#include "ostream.h" struct wrapper_fs_iter { struct fs_iter iter; @@ -78,7 +79,10 @@ void fs_wrapper_write_stream(struct fs_file *file) int fs_wrapper_write_stream_finish(struct fs_file *file, bool success) { if (!success) { - fs_write_stream_abort(file->parent, &file->output); + fs_write_stream_abort_error(file->parent, &file->output, + "write(%s) failed: %s", + o_stream_get_name(file->output), + o_stream_get_error(file->output)); return -1; } diff --git a/src/lib-storage/index/index-attachment.c b/src/lib-storage/index/index-attachment.c index 3bfb3d387e..4d0a5daae4 100644 --- a/src/lib-storage/index/index-attachment.c +++ b/src/lib-storage/index/index-attachment.c @@ -138,7 +138,9 @@ index_attachment_close_ostream(struct ostream *output, bool success, i_assert(attach->cur_file != NULL); if (ret < 0) - fs_write_stream_abort(attach->cur_file, &output); + fs_write_stream_abort_error(attach->cur_file, &output, "write(%s) failed: %s", + o_stream_get_name(output), + o_stream_get_error(output)); else if (fs_write_stream_finish(attach->cur_file, &output) < 0) { *error_r = t_strdup_printf("Couldn't create attachment %s: %s", fs_file_path(attach->cur_file), diff --git a/src/plugins/fs-compress/fs-compress.c b/src/plugins/fs-compress/fs-compress.c index e1e3ceafa3..f582c3bd54 100644 --- a/src/plugins/fs-compress/fs-compress.c +++ b/src/plugins/fs-compress/fs-compress.c @@ -201,7 +201,10 @@ static int fs_compress_write_stream_finish(struct fs_file *_file, bool success) if (file->temp_output != NULL) o_stream_destroy(&file->temp_output); if (file->super_output != NULL) - fs_write_stream_abort(_file->parent, &file->super_output); + fs_write_stream_abort_error(_file->parent, &file->super_output, + "write(%s) failed: %s", + o_stream_get_name(file->super_output), + o_stream_get_error(file->super_output)); return -1; }