From e2d6a03d20e8db291c3cbfc67082980c9a73b50e Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@dovecot.fi>
Date: Mon, 16 May 2016 21:02:09 +0300
Subject: [PATCH] Use o_stream_nsend*() to make sure write errors are caught.

---
 src/lib-sieve-tool/sieve-tool.c                   |  4 ++++
 src/lib-sieve/cmd-redirect.c                      |  9 +++------
 .../plugins/enotify/mailto/ntfy-mailto.c          |  2 +-
 src/lib-sieve/plugins/notify/cmd-notify.c         |  2 +-
 src/lib-sieve/plugins/vacation/cmd-vacation.c     |  2 +-
 .../plugins/vnd.dovecot/report/cmd-report.c       | 15 ++++++---------
 src/lib-sieve/sieve-actions.c                     |  8 +++-----
 src/lib-sieve/sieve-binary-dumper.c               |  8 ++++----
 src/lib-sieve/sieve-code-dumper.c                 |  4 ++--
 src/lib-sieve/sieve-result.c                      |  6 +++---
 src/lib-sieve/sieve.c                             | 10 ++++++++--
 src/managesieve-login/managesieve-proxy.c         | 10 +++++-----
 src/sieve-tools/sieve-filter.c                    |  6 ++++--
 src/sieve-tools/sieve-test.c                      |  5 +++--
 src/testsuite/testsuite-result.c                  |  5 +++--
 src/testsuite/testsuite-smtp.c                    |  8 +++++++-
 16 files changed, 58 insertions(+), 46 deletions(-)

diff --git a/src/lib-sieve-tool/sieve-tool.c b/src/lib-sieve-tool/sieve-tool.c
index c3039e8ee..ddee3180a 100644
--- a/src/lib-sieve-tool/sieve-tool.c
+++ b/src/lib-sieve-tool/sieve-tool.c
@@ -577,6 +577,10 @@ void sieve_tool_dump_binary_to
 			(void) sieve_hexdump(sbin, dumpstream);
 		else
 			(void) sieve_dump(sbin, dumpstream, FALSE);
+		if (o_stream_nfinish(dumpstream) < 0) {
+			i_fatal("write(%s) failed: %s", filename,
+				o_stream_get_error(dumpstream));
+		}
 		o_stream_destroy(&dumpstream);
 	} else {
 		i_fatal("Failed to create stream for sieve code dump.");
diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c
index 3dd28bca7..9827a4796 100644
--- a/src/lib-sieve/cmd-redirect.c
+++ b/src/lib-sieve/cmd-redirect.c
@@ -395,15 +395,12 @@ static int act_redirect_send
 		if ( new_msg_id != NULL )
 			rfc2822_header_write(hdr, "Message-ID", new_msg_id);
 
-		o_stream_send(output, str_data(hdr), str_len(hdr));
+		o_stream_nsend(output, str_data(hdr), str_len(hdr));
 	} T_END;
 
-	ret = o_stream_send_istream(output, input);
+	o_stream_nsend_istream(output, input);
 
-	/* blocking i/o required */
-	i_assert( ret != 0 );
-
-	if (ret < 0 && input->stream_errno != 0) {
+	if (input->stream_errno != 0) {
 		sieve_result_critical(aenv,
 			"redirect action: failed to read input message",
 			"redirect action: read(%s) failed: %s",
diff --git a/src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c b/src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c
index 5a2cd8b59..dc45abad5 100644
--- a/src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c
+++ b/src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c
@@ -632,7 +632,7 @@ static int ntfy_mailto_send
 		sieve_smtp_add_rcpt(sctx, recipients[i].normalized);
 
 	output = sieve_smtp_send(sctx);
-	o_stream_send(output, str_data(msg), str_len(msg));
+	o_stream_nsend(output, str_data(msg), str_len(msg));
 
 	if ( (ret=sieve_smtp_finish(sctx, &error)) <= 0 ) {
 		if (ret < 0)  {
diff --git a/src/lib-sieve/plugins/notify/cmd-notify.c b/src/lib-sieve/plugins/notify/cmd-notify.c
index bacbf31ef..74ec2f63a 100644
--- a/src/lib-sieve/plugins/notify/cmd-notify.c
+++ b/src/lib-sieve/plugins/notify/cmd-notify.c
@@ -776,7 +776,7 @@ static bool act_notify_send
 	str_printfa(msg, "\r\n%s\r\n", act->message);
 
 	output = sieve_smtp_send(sctx);
-	o_stream_send(output, str_data(msg), str_len(msg));
+	o_stream_nsend(output, str_data(msg), str_len(msg));
 
 	if ( (ret=sieve_smtp_finish(sctx, &error)) <= 0 ) {
 		if (ret < 0) {
diff --git a/src/lib-sieve/plugins/vacation/cmd-vacation.c b/src/lib-sieve/plugins/vacation/cmd-vacation.c
index 1f60c5835..755bcc96c 100644
--- a/src/lib-sieve/plugins/vacation/cmd-vacation.c
+++ b/src/lib-sieve/plugins/vacation/cmd-vacation.c
@@ -986,7 +986,7 @@ static int act_vacation_send
 	}
 
 	str_printfa(msg, "%s\r\n", ctx->reason);
-  o_stream_send(output, str_data(msg), str_len(msg));
+	o_stream_nsend(output, str_data(msg), str_len(msg));
 
 	/* Close smtp session */
 	if ( (ret=sieve_smtp_finish(sctx, &error)) <= 0 ) {
diff --git a/src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c b/src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c
index eb446297d..7e8f9226a 100644
--- a/src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c
+++ b/src/lib-sieve/plugins/vnd.dovecot/report/cmd-report.c
@@ -526,7 +526,7 @@ static int act_report_send
 	rfc2822_header_write(msg, "Content-Disposition", "inline");
 
 	str_printfa(msg, "\r\n%s\r\n\r\n", act->message);
-	o_stream_send(output, str_data(msg), str_len(msg));
+	o_stream_nsend(output, str_data(msg), str_len(msg));
 
 	/* Machine-readable report */
   str_truncate(msg, 0);
@@ -562,7 +562,7 @@ static int act_report_send
 	}
 	str_append(msg, "\r\n");
 
-	o_stream_send(output, str_data(msg), str_len(msg));
+	o_stream_nsend(output, str_data(msg), str_len(msg));
 
 	/* Original message */
   str_truncate(msg, 0);
@@ -577,7 +577,7 @@ static int act_report_send
 	rfc2822_header_write(msg,
 		"Content-Disposition", "attachment");
 	str_append(msg, "\r\n");
-	o_stream_send(output, str_data(msg), str_len(msg));
+	o_stream_nsend(output, str_data(msg), str_len(msg));
 
 	if (act->headers_only) {
 		struct message_size hdr_size;
@@ -594,12 +594,9 @@ static int act_report_send
 			"report action: failed to read input message");
 	}
 
-  ret = o_stream_send_istream(output, input);
+	o_stream_nsend_istream(output, input);
 
-	/* blocking i/o required */
-	i_assert( ret != 0 );
-
-	if ( ret < 0 && input->stream_errno != 0 ) {
+	if ( input->stream_errno != 0 ) {
 		/* Error; clean up */
 		sieve_result_critical(aenv,
 			"report action: failed to read input message",
@@ -615,7 +612,7 @@ static int act_report_send
 	if (!act->headers_only)
 		str_printfa(msg, "\r\n");
 	str_printfa(msg, "\r\n--%s--\r\n", boundary);
-  o_stream_send(output, str_data(msg), str_len(msg));
+  o_stream_nsend(output, str_data(msg), str_len(msg));
 
 	/* Finish sending message */
 	if ( (ret=sieve_smtp_finish(sctx, &error)) <= 0 ) {
diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c
index 6ab4b066c..e499e835b 100644
--- a/src/lib-sieve/sieve-actions.c
+++ b/src/lib-sieve/sieve-actions.c
@@ -876,7 +876,7 @@ static int sieve_action_do_reject_mail
 	str_printfa(hdr, "--%s\r\n", boundary);
 	rfc2822_header_write(hdr, "Content-Type", "message/rfc822");
 	str_append(hdr, "\r\n");
-	o_stream_send(output, str_data(hdr), str_len(hdr));
+	o_stream_nsend(output, str_data(hdr), str_len(hdr));
 
 	if (mail_get_hdr_stream(msgdata->mail, NULL, &input) == 0) {
     /* Note: If you add more headers, they need to be sorted.
@@ -893,15 +893,13 @@ static int sieve_action_do_reject_mail
 		N_ELEMENTS(exclude_headers),
 		*null_header_filter_callback, (void *)NULL);
 
-    ret = o_stream_send_istream(output, input);
+    o_stream_nsend_istream(output, input);
     i_stream_unref(&input);
-
-    i_assert(ret != 0);
   }
 
   str_truncate(hdr, 0);
   str_printfa(hdr, "\r\n\r\n--%s--\r\n", boundary);
-  o_stream_send(output, str_data(hdr), str_len(hdr));
+  o_stream_nsend(output, str_data(hdr), str_len(hdr));
 
 	if ( (ret=sieve_smtp_finish(sctx, &error)) <= 0 ) {
 		if ( ret < 0 ) {
diff --git a/src/lib-sieve/sieve-binary-dumper.c b/src/lib-sieve/sieve-binary-dumper.c
index 7a4b2283e..48bb9c71e 100644
--- a/src/lib-sieve/sieve-binary-dumper.c
+++ b/src/lib-sieve/sieve-binary-dumper.c
@@ -71,7 +71,7 @@ void sieve_binary_dumpf
 	str_vprintfa(outbuf, fmt, args);
 	va_end(args);
 
-	o_stream_send(denv->stream, str_data(outbuf), str_len(outbuf));
+	o_stream_nsend(denv->stream, str_data(outbuf), str_len(outbuf));
 }
 
 void sieve_binary_dump_sectionf
@@ -86,7 +86,7 @@ void sieve_binary_dump_sectionf
 	str_printfa(outbuf, ":\n\n");
 	va_end(args);
 
-	o_stream_send(denv->stream, str_data(outbuf), str_len(outbuf));
+	o_stream_nsend(denv->stream, str_data(outbuf), str_len(outbuf));
 }
 
 /*
@@ -279,13 +279,13 @@ void sieve_binary_dumper_hexdump
 			}
 
 			str_append(line, "|\n");
-			o_stream_send(stream, str_data(line), str_len(line));
+			o_stream_nsend(stream, str_data(line), str_len(line));
 			str_truncate(line, 0);
 			offset += len;
 		}
 
 		str_printfa(line, "%08llx\n", (unsigned long long) offset);
-		o_stream_send(stream, str_data(line), str_len(line));
+		o_stream_nsend(stream, str_data(line), str_len(line));
 	}
 }
 
diff --git a/src/lib-sieve/sieve-code-dumper.c b/src/lib-sieve/sieve-code-dumper.c
index 3c098b669..c761200bd 100644
--- a/src/lib-sieve/sieve-code-dumper.c
+++ b/src/lib-sieve/sieve-code-dumper.c
@@ -163,7 +163,7 @@ void sieve_code_dumpf
 	str_append_c(outbuf, '\n');
 	va_end(args);
 
-	o_stream_send(denv->stream, str_data(outbuf), str_len(outbuf));
+	o_stream_nsend(denv->stream, str_data(outbuf), str_len(outbuf));
 }
 
 static inline void sieve_code_line_mark
@@ -246,7 +246,7 @@ void sieve_code_dumper_run(struct sieve_code_dumper *cdumper)
 	address = &(denv->offset);
 
 	/* Heading */
-	o_stream_send_str(denv->stream, "Address   Line  Code\n");
+	o_stream_nsend_str(denv->stream, "Address   Line  Code\n");
 
 	/* Load debug block */
 	sieve_code_mark(denv);
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index 908e4fd00..014fcbc96 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -728,7 +728,7 @@ void sieve_result_vprintf
 
 	str_vprintfa(outbuf, fmt, args);
 
-	o_stream_send(penv->stream, str_data(outbuf), str_len(outbuf));
+	o_stream_nsend(penv->stream, str_data(outbuf), str_len(outbuf));
 }
 
 void sieve_result_printf
@@ -753,7 +753,7 @@ void sieve_result_action_printf
 	str_append_c(outbuf, '\n');
 	va_end(args);
 
-	o_stream_send(penv->stream, str_data(outbuf), str_len(outbuf));
+	o_stream_nsend(penv->stream, str_data(outbuf), str_len(outbuf));
 }
 
 void sieve_result_seffect_printf
@@ -768,7 +768,7 @@ void sieve_result_seffect_printf
 	str_append_c(outbuf, '\n');
 	va_end(args);
 
-	o_stream_send(penv->stream, str_data(outbuf), str_len(outbuf));
+	o_stream_nsend(penv->stream, str_data(outbuf), str_len(outbuf));
 }
 
 static void sieve_result_print_side_effects
diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c
index 0c876eed5..f82609c13 100644
--- a/src/lib-sieve/sieve.c
+++ b/src/lib-sieve/sieve.c
@@ -865,6 +865,7 @@ int sieve_trace_log_create
 			return -1;
 		}
 		output = o_stream_create_fd_autoclose(&fd, 0);
+		o_stream_set_name(output, path);
 	}
 
 	trace_log = i_new(struct sieve_trace_log, 1);
@@ -935,7 +936,7 @@ void sieve_trace_log_write_line
 	struct const_iovec iov[2];
 
 	if (line == NULL) {
-		o_stream_send_str(trace_log->output, "\n");
+		o_stream_nsend_str(trace_log->output, "\n");
 		return;
 	}
 
@@ -944,7 +945,7 @@ void sieve_trace_log_write_line
 	iov[0].iov_len = str_len(line);
 	iov[1].iov_base = "\n";
 	iov[1].iov_len = 1;
-	o_stream_sendv(trace_log->output, iov, 2);
+	o_stream_nsendv(trace_log->output, iov, 2);
 }
 
 void sieve_trace_log_free(struct sieve_trace_log **_trace_log)
@@ -953,6 +954,11 @@ void sieve_trace_log_free(struct sieve_trace_log **_trace_log)
 
 	*_trace_log = NULL;
 
+	if (o_stream_nfinish(trace_log->output) < 0) {
+		i_error("write(%s) failed: %s",
+			o_stream_get_name(trace_log->output),
+			o_stream_get_error(trace_log->output));
+	}
 	o_stream_destroy(&trace_log->output);
 	i_free(trace_log);
 }
diff --git a/src/managesieve-login/managesieve-proxy.c b/src/managesieve-login/managesieve-proxy.c
index fa96c783b..943430637 100644
--- a/src/managesieve-login/managesieve-proxy.c
+++ b/src/managesieve-login/managesieve-proxy.c
@@ -392,7 +392,7 @@ int managesieve_proxy_parse_line(struct client *client, const char *line)
 				msieve_client->proxy_state = MSIEVE_PROXY_STATE_AUTH;
 			}
 
-			(void)o_stream_send(output, str_data(command), str_len(command));
+			o_stream_nsend(output, str_data(command), str_len(command));
 		}
 		return 0;
 
@@ -444,7 +444,7 @@ int managesieve_proxy_parse_line(struct client *client, const char *line)
 				}
 				msieve_client->proxy_state = MSIEVE_PROXY_STATE_AUTH;
 			}
-			(void)o_stream_send(output, str_data(command), str_len(command));
+			o_stream_nsend(output, str_data(command), str_len(command));
 		}
 		return 0;
 
@@ -457,7 +457,7 @@ int managesieve_proxy_parse_line(struct client *client, const char *line)
 				client_proxy_failed(client, TRUE);
 				return -1;
 			}
-			(void)o_stream_send(output, str_data(command), str_len(command));
+			o_stream_nsend(output, str_data(command), str_len(command));
 			msieve_client->proxy_state = MSIEVE_PROXY_STATE_AUTH;
 			return 0;
 		}
@@ -484,7 +484,7 @@ int managesieve_proxy_parse_line(struct client *client, const char *line)
 				client_proxy_failed(client, TRUE);
 				return -1;
 			}
-			(void)o_stream_send(output, str_data(command), str_len(command));
+			o_stream_nsend(output, str_data(command), str_len(command));
 			return 0;
 		}
 
@@ -500,7 +500,7 @@ int managesieve_proxy_parse_line(struct client *client, const char *line)
 			/* Send this line to client. */
 			str_append(str, line );
 			str_append(str, "\r\n");
-			(void)o_stream_send(client->output, str_data(str), str_len(str));
+			o_stream_nsend(client->output, str_data(str), str_len(str));
 
 			(void)client_skip_line(msieve_client);
 			client_proxy_finish_destroy_client(client);
diff --git a/src/sieve-tools/sieve-filter.c b/src/sieve-tools/sieve-filter.c
index 8b4f12d8b..740c497e2 100644
--- a/src/sieve-tools/sieve-filter.c
+++ b/src/sieve-tools/sieve-filter.c
@@ -132,7 +132,7 @@ static int filter_message
 		sieve_error_handler_unref(&action_ehandler);
 
 	} else {
-		(void)o_stream_send_str(sfctx->teststream,
+		o_stream_nsend_str(sfctx->teststream,
 			t_strdup_printf(">> Filtering message:\n\n"
 				"  ID:      %s\n"
 			  "  Date:    %s\n"
@@ -288,8 +288,10 @@ static int filter_mailbox
 	sfctx.data = sfdata;
 
 	/* Create test stream */
-	if ( !sfdata->execute )
+	if ( !sfdata->execute ) {
 		sfctx.teststream = o_stream_create_fd(1, 0, FALSE);
+		o_stream_set_no_error_handling(sfctx.teststream, TRUE);
+	}
 
 	/* Start move mailbox transaction */
 
diff --git a/src/sieve-tools/sieve-test.c b/src/sieve-tools/sieve-test.c
index 3d884544e..cbfc52cc6 100644
--- a/src/sieve-tools/sieve-test.c
+++ b/src/sieve-tools/sieve-test.c
@@ -281,6 +281,7 @@ int main(int argc, char **argv)
 		if ( !execute ) {
 			action_ehandler = NULL;
 			teststream = o_stream_create_fd(1, 0, FALSE);
+			o_stream_set_no_error_handling(teststream, TRUE);
 		} else {
 			action_ehandler = sieve_prefix_ehandler_create
 				(ehandler, NULL, t_strdup_printf("msgid=%s",
@@ -342,7 +343,7 @@ int main(int argc, char **argv)
 			sfiles = array_get(&scriptfiles, &count);
 			for ( i = 0; i < count && more; i++ ) {
 				if ( teststream != NULL )
-					o_stream_send_str(teststream,
+					o_stream_nsend_str(teststream,
 						t_strdup_printf("\n## Executing script: %s\n", sfiles[i]));
 
 				/* Close previous script */
@@ -371,7 +372,7 @@ int main(int argc, char **argv)
 			/* Execute/Test main script */
 			if ( more && ret > 0 ) {
 				if ( teststream != NULL )
-					o_stream_send_str(teststream,
+					o_stream_nsend_str(teststream,
 						t_strdup_printf("## Executing script: %s\n", scriptfile));
 
 				/* Close previous script */
diff --git a/src/testsuite/testsuite-result.c b/src/testsuite/testsuite-result.c
index 47bc60116..49dc7a890 100644
--- a/src/testsuite/testsuite-result.c
+++ b/src/testsuite/testsuite-result.c
@@ -87,10 +87,11 @@ void testsuite_result_print
 	struct ostream *out;
 
 	out = o_stream_create_fd(1, 0, FALSE);
+	o_stream_set_no_error_handling(out, TRUE);
 
-	o_stream_send_str(out, "\n--");
+	o_stream_nsend_str(out, "\n--");
 	sieve_result_print(_testsuite_result, renv->scriptenv, out, NULL);
-	o_stream_send_str(out, "--\n\n");
+	o_stream_nsend_str(out, "--\n\n");
 
 	o_stream_destroy(&out);
 }
diff --git a/src/testsuite/testsuite-smtp.c b/src/testsuite/testsuite-smtp.c
index ee5578f1e..b273135c5 100644
--- a/src/testsuite/testsuite-smtp.c
+++ b/src/testsuite/testsuite-smtp.c
@@ -123,12 +123,18 @@ int testsuite_smtp_finish
 	void *handle, const char **error_r ATTR_UNUSED)
 {
 	struct testsuite_smtp *smtp = (struct testsuite_smtp *) handle;
+	int ret = 1;
 
+	if (o_stream_nfinish(smtp->output) < 0) {
+		i_error("write(%s) failed: %s", smtp->msg_file,
+			o_stream_get_error(smtp->output));
+		ret = -1;
+	}
 	o_stream_unref(&smtp->output);
 	i_free(smtp->msg_file);
 	i_free(smtp->return_path);
 	i_free(smtp);
-	return 1;
+	return ret;
 }
 
 /*
-- 
GitLab