Appendfile: when evaluating quota use attemd to link counts
authorJeremy Harris <jgh146exb@wizmail.org>
Thu, 15 Aug 2019 12:47:04 +0000 (13:47 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Thu, 15 Aug 2019 13:08:33 +0000 (14:08 +0100)
doc/doc-docbook/spec.xfpt
doc/doc-txt/ChangeLog
src/src/transports/appendfile.c

index 8bba6fe..63db8ef 100644 (file)
@@ -22859,6 +22859,15 @@ sometimes add other information onto the ends of message filenames.
 
 Section &<<SECID136>>& contains further information.
 
+.new
+This option should not be used when other message-handling software
+may duplicate messages by making hardlinks to the files.  When that is done Exim
+will count the message size once for each filename, in contrast with the actual
+disk usage.  When the option is not set, calculating total usage requires
+a system-call per file to get the size; the number of links is then available also
+as is used to adjust the effective size.
+.wen
+
 
 .option quota_warn_message appendfile string&!! "see below"
 See below for the use of this option. If it is not set when
index 6d1b263..c3972d2 100644 (file)
@@ -164,12 +164,15 @@ JH/34 Fix crash after TLS shutdown.  When the TCP/SMTP channel was left open,
 JH/35 Bug 2409: filter out-of-spec chars from callout response before using
       them in our smtp response.
 
-JH/35 Have the general router option retry_use_local_part default to true when
+JH/36 Have the general router option retry_use_local_part default to true when
       any of the restrictive preconditions are set (to anything).  Previously it
       was only for check_local user.  The change removes one item of manual
       configuration which is required for proper retries when a remote router
       handles a subset of addresses for a domain.
 
+JH/37 Appendfile: when evaluating quota use (non-quota_size_regex) take the file
+      link count into consideration.
+
 
 Exim version 4.92
 -----------------
index 5d23008..8f26c71 100644 (file)
@@ -773,10 +773,9 @@ int count = *countptr;
 struct dirent *ent;
 struct stat statbuf;
 
-dir = opendir(CS dirname);
-if (dir == NULL) return 0;
+if (!(dir = opendir(CS dirname))) return 0;
 
-while ((ent = readdir(dir)) != NULL)
+while ((ent = readdir(dir)))
   {
   uschar * path, * name = US ent->d_name;
 
@@ -815,13 +814,12 @@ while ((ent = readdir(dir)) != NULL)
     DEBUG(D_transport)
       debug_printf("check_dir_size: stat error %d for %s: %s\n", errno, path,
         strerror(errno));
-    continue;
     }
-
-  if ((statbuf.st_mode & S_IFMT) == S_IFREG)
-    sum += statbuf.st_size;
-  else if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
-    sum += check_dir_size(path, &count, regex);
+  else
+    if ((statbuf.st_mode & S_IFMT) == S_IFREG)
+      sum += statbuf.st_size / statbuf.st_nlink;
+    else if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
+      sum += check_dir_size(path, &count, regex);
   }
 
 closedir(dir);