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

Top Page

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 10:37, Philip Hazel wrote:
> On Sun, 22 Apr 2007, Magnus Holmgren wrote:
> > Hmm, AFAICT there are quite a few variables that need updating:
> > body_zerocount, message_size, message_body_size, and message_linecount.
> > There doesn't seem to be much point updating just one of them, is there?
>
> That's why writing to the fd is "not recommended" :-)
>
> This is a can of worms which I would rather not open.


At least the can could be better labled.

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.

After the message body has been written, the number of "lines" in it always
equals the number of LFs in it, doesn't it? If local_scan() doesn't terminate
the last line or does other funny business we won't guarantee that
body_linecount is correct.

How to detect whether the fd has been written to? Compare mtimes? Compare
nanosecond mtimes? Compare the size (assuming that any operation that alters
the number of lines should alter the size)? Checking the file offset
(specifying that local_scan() functions should *not* rewind fd to
SPOOL_DATA_START_OFFSET after writing to it (but after reading it - nah))?

-- 
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 09:30:14 -0000
@@ -3104,6 +3104,10 @@


 if (rc == LOCAL_SCAN_ACCEPT)
   {
+  int old_body_size = message_body_size;
+  int old_body_linecount = body_linecount;
+  int ch;
+
   if (local_scan_data != NULL)
     {
     uschar *s;
@@ -3118,6 +3122,20 @@
     }
   if (recipients_count == 0 && blackholed_by == NULL)
     blackholed_by = US"local_scan";
+
+  /* Recalculate message properties in case local_scan() altered it. */
+  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_body_size = (fstat(data_fd, &statbuf) == 0)?
+    statbuf.st_size - SPOOL_DATA_START_OFFSET : -1;
+  message_size += (message_body_size - old_body_size);
+  message_linecount += (body_linecount - old_body_linecount);
+  
   }


/* Message rejected: newlines permitted in local_scan_data to generate