Re: [exim-dev] local_scan() and the fd

Top Page
Delete this message
Reply to this message
Author: Magnus Holmgren
Date:  
To: exim-dev
Subject: Re: [exim-dev] local_scan() and the fd
On Monday 23 April 2007 11:57, Magnus Holmgren wrote:
> Please have a look at the attached patch anyway. If the recalculation can
> be skipped when the fd *hasn't* been written to, at least it shouldn't make
> matters worse.


Here's a new version that compares the size and the mtime. Should work in the
case of SA-Exim, but it would have been nice if there were some way to set
a "checkpoint" and later ask if any writing has occurred since that
checkpoint.

Will fseek() cause the stream layer to forget what was previously fwritten,
even if the file position is unchanged, or can getc() return old data?

-- 
Magnus Holmgren        holmgren@???
                       (No Cc of list mail needed, thanks)

Index: src/receive.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/receive.c,v
retrieving revision 1.37
diff -u -r1.37 receive.c
--- src/receive.c    16 Apr 2007 10:31:58 -0000    1.37
+++ src/receive.c    23 Apr 2007 13:38:05 -0000
@@ -3104,6 +3104,34 @@


 if (rc == LOCAL_SCAN_ACCEPT)
   {
+  int old_body_size = message_body_size;
+  int old_body_linecount = body_linecount;
+  time_t old_mtime = statbuf.st_mtime;
+  int ch;
+
+  /* Recalculate message properties in case local_scan() altered it. */
+  if (fstat(data_fd, &statbuf) != 0)
+    {
+    log_write(0, LOG_MAIN|LOG_PANIC,
+                "fstat(data_fd) failed! Did local_scan() close it?");
+    message_id[0] = 0;            /* Indicate no message accepted */
+    smtp_reply = US"451 Temporary local problem";
+    goto TIDYUP;
+    }
+  message_body_size = statbuf.st_size - SPOOL_DATA_START_OFFSET;
+  if (message_body_size != old_body_size || statbuf.st_mtime != old_mtime)
+    {
+    message_size += (message_body_size - old_body_size);
+    fseek(data_file, (long int)SPOOL_DATA_START_OFFSET, SEEK_SET);
+    body_linecount = body_zerocount = 0;
+    while ((ch = getc(data_file)) != EOF)
+      {
+      if (ch == '\n') body_linecount++;
+      else if (ch == '\0') body_zerocount++;
+      }
+    message_linecount += (body_linecount - old_body_linecount);
+    }
+
   if (local_scan_data != NULL)
     {
     uschar *s;