]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: ostream-file - Fix using sendfile() when input stream is ends unexpectedly early
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Thu, 12 Mar 2020 10:58:11 +0000 (12:58 +0200)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Fri, 27 Mar 2020 14:35:20 +0000 (14:35 +0000)
Handle this the same as if writing was done without sendfile(), i.e. ignore
the problem and just return EOF in input stream early.

src/lib/ostream-file.c
src/lib/test-ostream-file.c

index 869a670ddcfb7778bc174cfb936caecfb1c4cba8..b1f3f9f592a0d3fa31057793d4561f9420f25053 100644 (file)
@@ -777,8 +777,13 @@ io_stream_sendfile(struct ostream_private *outstream,
                ret = safe_sendfile(foutstream->fd, in_fd, &offset,
                                    MAX_SSIZE_T(send_size));
                if (ret <= 0) {
-                       if (ret == 0)
-                               break;
+                       if (ret == 0) {
+                               /* Unexpectedly early EOF at input */
+                               i_stream_seek(instream, v_offset);
+                               instream->eof = TRUE;
+                               *res_r = OSTREAM_SEND_ISTREAM_RESULT_FINISHED;
+                               return TRUE;
+                       }
                        if (foutstream->file) {
                                if (errno == EINTR) {
                                        /* automatically retry */
index d61c5a819cd587796cba66bb4d666b9cba91555e..d4a9eff88e7b94472b440860d67e549068524cf4 100644 (file)
@@ -164,8 +164,16 @@ static void test_ostream_file_send_istream_sendfile(void)
        test_assert(read(sock_fd[1], buf, sizeof(buf)) == 4 &&
                    memcmp(buf, "defg", 4) == 0);
        i_stream_unref(&input2);
-       i_stream_unref(&input);
 
+       /* test reading past EOF */
+       i_stream_seek(input, 0);
+       input2 = i_stream_create_limit(input, 20);
+       test_assert(o_stream_send_istream(output, input2) == OSTREAM_SEND_ISTREAM_RESULT_FINISHED);
+       test_assert(input2->v_offset == 10);
+       test_assert(output->offset == 14);
+       i_stream_unref(&input2);
+
+       i_stream_unref(&input);
        o_stream_destroy(&output);
        i_close_fd(&sock_fd[1]);