bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2015-2018 Dovecot authors, see the included COPYING file */
9294b9ad2eb112258c247906b53010664f84e57bTimo Sirainenstatic void o_stream_failure_at_destroy(struct iostream_private *stream)
9294b9ad2eb112258c247906b53010664f84e57bTimo Siraineno_stream_failure_at_sendv(struct ostream_private *stream,
9294b9ad2eb112258c247906b53010664f84e57bTimo Sirainen const struct const_iovec *iov, unsigned int iov_count)
9294b9ad2eb112258c247906b53010664f84e57bTimo Sirainen unsigned int i;
a81be83a3bb00b7b31b832f50bd8542e62a71891Timo Sirainen uoff_t bytes_until_failure, blocking_bytes_count = 0;
a81be83a3bb00b7b31b832f50bd8542e62a71891Timo Sirainen /* blocking ostream must return either a full success or a
a81be83a3bb00b7b31b832f50bd8542e62a71891Timo Sirainen failure. if the current write would go past failure_offset,
a81be83a3bb00b7b31b832f50bd8542e62a71891Timo Sirainen return a failure now before writing anything. */
a81be83a3bb00b7b31b832f50bd8542e62a71891Timo Sirainen for (i = 0; i < iov_count; i++)
a81be83a3bb00b7b31b832f50bd8542e62a71891Timo Sirainen /* if we're exactly at the failure offset after this
a81be83a3bb00b7b31b832f50bd8542e62a71891Timo Sirainen write, fail it only on the next write. */
a81be83a3bb00b7b31b832f50bd8542e62a71891Timo Sirainen if (fstream->failure_offset <= stream->ostream.offset + blocking_bytes_count) {
9294b9ad2eb112258c247906b53010664f84e57bTimo Sirainen bytes_until_failure = fstream->failure_offset - stream->ostream.offset;
9294b9ad2eb112258c247906b53010664f84e57bTimo Sirainen iov_dup = i_new(struct const_iovec, iov_count);
9294b9ad2eb112258c247906b53010664f84e57bTimo Sirainen for (i = 0; i < iov_count; i++) {
9294b9ad2eb112258c247906b53010664f84e57bTimo Sirainen if (iov_dup[i].iov_len >= bytes_until_failure) {
9294b9ad2eb112258c247906b53010664f84e57bTimo Sirainen ret = o_stream_sendv(stream->parent, iov_dup, iov_dup_count);
9294b9ad2eb112258c247906b53010664f84e57bTimo Siraineno_stream_failure_at_flush(struct ostream_private *stream)
9294b9ad2eb112258c247906b53010664f84e57bTimo Siraineno_stream_create_failure_at(struct ostream *output, uoff_t failure_offset,
9294b9ad2eb112258c247906b53010664f84e57bTimo Sirainen fstream = i_new(struct failure_at_ostream, 1);
9294b9ad2eb112258c247906b53010664f84e57bTimo Sirainen fstream->ostream.sendv = o_stream_failure_at_sendv;
9294b9ad2eb112258c247906b53010664f84e57bTimo Sirainen fstream->ostream.flush = o_stream_failure_at_flush;
9294b9ad2eb112258c247906b53010664f84e57bTimo Sirainen fstream->ostream.iostream.destroy = o_stream_failure_at_destroy;
9294b9ad2eb112258c247906b53010664f84e57bTimo Sirainen fstream->error_string = i_strdup(error_string);
9294b9ad2eb112258c247906b53010664f84e57bTimo Sirainen return o_stream_create(&fstream->ostream, output,
9294b9ad2eb112258c247906b53010664f84e57bTimo Siraineno_stream_create_failure_at_flush(struct ostream *output, const char *error_string)
9294b9ad2eb112258c247906b53010664f84e57bTimo Sirainen fstream = i_new(struct failure_at_ostream, 1);
9294b9ad2eb112258c247906b53010664f84e57bTimo Sirainen fstream->ostream.flush = o_stream_failure_at_flush;
9294b9ad2eb112258c247906b53010664f84e57bTimo Sirainen fstream->ostream.iostream.destroy = o_stream_failure_at_destroy;
9294b9ad2eb112258c247906b53010664f84e57bTimo Sirainen fstream->error_string = i_strdup(error_string);