CHUNKING / wire-format spool: use block-copies for receiption
[exim.git] / src / src / receive.c
index b03ab71ed2353eede33dbc5c474e53362658d47e..28da47f838b0126ed4948d0dec48048e92ed27f9 100644 (file)
@@ -1026,32 +1026,34 @@ int ch;
 DEBUG(D_receive) debug_printf("CHUNKING: writing spoolfile in wire format\n");
 spool_file_wireformat = TRUE;
 
-/* Unfortunately cannot use sendfile() even if not TLS
-as that requires (on linux) mmap-like operations on the input fd.
-
-XXX but worthwhile doing a block interface to the bdat_getc buffer
-in the future */
-
-for (;;) switch (ch = bdat_getc(GETC_BUFFER_UNLIMITED))
+for (;;)
   {
-  case EOF: return END_EOF;
-  case EOD: return END_DOT;
-  case ERR: return END_PROTOCOL;
+  if (chunking_data_left > 0)
+    {
+    unsigned len = MAX(chunking_data_left, thismessage_size_limit - message_size + 1);
+    uschar * buf = bdat_getbuf(&len);
 
-  default:
-    message_size++;
-/*XXX not done:
-linelength
-max_received_linelength
-body_linecount
-body_zerocount
-*/
-    if (fout)
-      {
-      if (fputc(ch, fout) == EOF) return END_WERROR;
-      if (message_size > thismessage_size_limit) return END_SIZE;
-      }
-    break;
+    message_size += len;
+    if (fout && fwrite(buf, len, 1, fout) != 1) return END_WERROR;
+    }
+  else switch (ch = bdat_getc(GETC_BUFFER_UNLIMITED))
+    {
+    case EOF: return END_EOF;
+    case EOD: return END_DOT;
+    case ERR: return END_PROTOCOL;
+
+    default:
+      message_size++;
+  /*XXX not done:
+  linelength
+  max_received_linelength
+  body_linecount
+  body_zerocount
+  */
+      if (fout && fputc(ch, fout) == EOF) return END_WERROR;
+      break;
+    }
+  if (message_size > thismessage_size_limit) return END_SIZE;
   }
 /*NOTREACHED*/
 }