Re: [exim] Quota over 2GB supported?

Pàgina inicial
Delete this message
Reply to this message
Autor: Michael Haardt
Data:  
A: exim-users
Assumpte: Re: [exim] Quota over 2GB supported?
On Fri, Apr 29, 2005 at 10:25:46AM +0100, Philip Hazel wrote:
> On Thu, 28 Apr 2005, Christian Kuehn wrote:
>
> > Is this problem fixed in 4.51 (rc released today by Philip) ??
>
> No. And I have not released 4.51, only some candidate code for testing.
> The patch was too complicated and Michael's own comments led me to
> believe that it was incomplete. I want to get 4.51 out soon because it
> fixes important bugs, and I don't have time at the moment to study the
> problem deeply enough. I'm afraid you'll have to live with the patch for
> a while.


The patch *is* incomplete, as it does not fix maildirsize and
transports/tf_maildir.c uses check_dir_size() as well and probably
needs to be fixed. It's a quick hack and below the usual code
quality of Exim, so I agree with Philip this shouldn't be integrated
under pressure of getting a release out that contains important and
tested bug fixes.

I append my patch for the 4.51 release candidate for those who want to
test/use it. And remember: After the release is before the release. :-)

Michael
----------------------------------------------------------------------
--- src/transports/appendfile.c.orig    2005-04-28 15:49:15.000000000 +0200
+++ src/transports/appendfile.c    2005-04-28 17:23:31.000000000 +0200
@@ -232,6 +232,21 @@
 };



+const unsigned char *offtostr(off_t n)
+ {
+ static unsigned char buf[128];
+ unsigned char *t;
+ size_t size,capacity;
+
+ size=capacity=0;
+ t=buf+sizeof(buf)-1;
+ *t='\0';
+ if (n==0) *--t='0';
+ else while (n) { *--t=n%10+'0'; n/=10; }
+ return string_cat(NULL,&size,&capacity,t,buf-t+1);
+ }
+
+

 /*************************************************
 *              Setup entry point                 *
@@ -259,8 +274,7 @@
 appendfile_transport_options_block *ob =
   (appendfile_transport_options_block *)(tblock->options_block);
 uschar *q = ob->quota;
-int *v = &(ob->quota_value);
-int default_value = 0;
+double default_value = 0.0;
 int i;


 addrlist = addrlist;    /* Keep picky compilers happy */
@@ -271,9 +285,10 @@


 for (i = 0; i < 5; i++)
   {
-  if (q == NULL) *v = default_value; else
+  double d;
+
+  if (q == NULL) d = default_value; else
     {
-    double d;
     uschar *rest;
     uschar *s = expand_string(q);


@@ -315,30 +330,33 @@
       return FAIL;
       }


-    *v = (int)d;
     }


   switch (i)
     {
     case 0:
+    ob->quota_value = (off_t)d;
     q = ob->quota_filecount;
-    v = &(ob->quota_filecount_value);
     break;


     case 1:
+    ob->quota_filecount_value = (int)d;
     q = ob->quota_warn_threshold;
-    v = &(ob->quota_warn_threshold_value);
     break;


     case 2:
+    ob->quota_warn_threshold_value = (off_t)d;
     q = ob->mailbox_size_string;
-    v = &(ob->mailbox_size_value);
-    default_value = -1;
+    default_value = -1.0;
     break;


     case 3:
+    ob->mailbox_size_value = (off_t)d;
     q = ob->mailbox_filecount_string;
-    v = &(ob->mailbox_filecount_value);
+    break;
+
+    case 4:
+    ob->mailbox_filecount_value = (int)d;
     break;
     }
   }
@@ -705,11 +723,11 @@
                 zero if the directory cannot be opened
 */


-int
+off_t
 check_dir_size(uschar *dirname, int *countptr, const pcre *regex)
 {
 DIR *dir;
-int sum = 0;
+off_t sum = 0;
 int count = *countptr;
 struct dirent *ent;
 struct stat statbuf;
@@ -739,7 +757,7 @@
         {
         sum += size;
         DEBUG(D_transport)
-          debug_printf("check_dir_size: size from %s is %d\n", name, size);
+          debug_printf("check_dir_size: size from %s is %s\n", name, offtostr(size));
         continue;
         }
       }
@@ -773,14 +791,12 @@


closedir(dir);
DEBUG(D_transport)
- debug_printf("check_dir_size: dir=%s sum=%d count=%d\n", dirname, sum, count);
+ debug_printf("check_dir_size: dir=%s sum=%s count=%d\n", dirname, offtostr(sum), count);
*countptr = count;
return sum;
}


-
-
 /*************************************************
 *         Apply a lock to a file descriptor      *
 *************************************************/
@@ -877,7 +893,7 @@
 static int
 copy_mbx_message(int to_fd, int from_fd, int saved_size)
 {
-int used, size;
+off_t used, size;
 struct stat statbuf;


/* If the current mailbox size is zero, write a header block */
@@ -1206,8 +1222,8 @@
gid_t gid = getegid();
int mbformat;
int mode = (addr->mode > 0)? addr->mode : ob->mode;
-int saved_size = -1;
-int mailbox_size = ob->mailbox_size_value;
+off_t saved_size = -1;
+off_t mailbox_size = ob->mailbox_size_value;
int mailbox_filecount = ob->mailbox_filecount_value;
int hd = -1;
int fd = -1;
@@ -1336,10 +1352,10 @@

 DEBUG(D_transport)
   {
-  debug_printf("appendfile: mode=%o notify_comsat=%d quota=%d warning=%d%s\n"
+  debug_printf("appendfile: mode=%o notify_comsat=%d quota=%s warning=%s%s\n"
     "  %s=%s format=%s\n  message_prefix=%s\n  message_suffix=%s\n  "
     "maildir_use_size_file=%s\n",
-    mode, ob->notify_comsat, ob->quota_value, ob->quota_warn_threshold_value,
+    mode, ob->notify_comsat, offtostr(ob->quota_value), offtostr(ob->quota_warn_threshold_value),
     ob->quota_warn_threshold_is_percent? "%" : "",
     isdirectory? "directory" : "file",
     path, mailbox_formats[mbformat],
@@ -2116,30 +2132,13 @@
     goto RETURN;
     }


-  #ifdef SUPPORT_MAILDIR
-  /* For a maildir delivery, ensure that all the relevant directories exist */
-
-  if (mbformat == mbf_maildir && !maildir_ensure_directories(path, addr,
-    ob->create_directory, ob->dirmode))
-      return FALSE;
-  #endif  /* SUPPORT_MAILDIR */
-
-  /* If we are going to do a quota check, of if maildir_use_size_file is set
-  for a maildir delivery, compile the regular expression if there is one. We
-  may also need to adjust the path that is used. We need to do this for
-  maildir_use_size_file even if the quota is unset, because we still want to
-  create the file. When maildir support is not compiled,
-  ob->maildir_use_size_file is always FALSE. */
-
-  if (ob->quota_value > 0 || THRESHOLD_CHECK || ob->maildir_use_size_file)
-    {
-    const uschar *error;
-    int offset;
-
     /* Compile the regex if there is one */


     if (ob->quota_size_regex != NULL)
       {
+      const uschar *error;
+      int offset;
+
       regex = pcre_compile(CS ob->quota_size_regex, PCRE_COPT,
         (const char **)&error, &offset, NULL);
       if (regex == NULL)
@@ -2156,6 +2155,23 @@
         }
       }


+  #ifdef SUPPORT_MAILDIR
+  /* For a maildir delivery, ensure that all the relevant directories exist */
+
+  if (mbformat == mbf_maildir && !maildir_ensure_directories(path, addr,
+    ob->create_directory, ob->dirmode))
+      return FALSE;
+  #endif  /* SUPPORT_MAILDIR */
+
+  /* If we are going to do a quota check, of if maildir_use_size_file is set
+  for a maildir delivery, compile the regular expression if there is one. We
+  may also need to adjust the path that is used. We need to do this for
+  maildir_use_size_file even if the quota is unset, because we still want to
+  create the file. When maildir support is not compiled,
+  ob->maildir_use_size_file is always FALSE. */
+
+  if (ob->quota_value > 0 || THRESHOLD_CHECK || ob->maildir_use_size_file)
+    {
     /* Use an explicitly configured directory if set */


     if (ob->quota_directory != NULL)
@@ -2211,6 +2227,7 @@
     #endif  /* SUPPORT_MAILDIR */
     }


+ #ifdef SUPPORT_MAILDIR
/* If we are using maildirsize files, we need to ensure that such a file
exists and, if necessary, recalculate its contents. As a byproduct of this,
we obtain the current size of the maildir. If no quota is to be enforced
@@ -2220,7 +2237,6 @@
Another regular expression is used to determine which directories inside the
maildir are going to be counted. */

-  #ifdef SUPPORT_MAILDIR
   if (ob->maildir_use_size_file)
     {
     const pcre *dir_regex = NULL;
@@ -2254,7 +2270,7 @@
 /*  if (???? || ob->quota_value > 0) */


       {
-      int size, filecount;
+      int size = 0, filecount = 0;


       maildirsize_fd = maildir_ensure_sizefile(check_path, ob, regex, dir_regex,
         &size, &filecount);
@@ -2295,7 +2311,7 @@
   if ((mailbox_size < 0 || mailbox_filecount < 0) &&
       (ob->quota_value > 0 || THRESHOLD_CHECK))
     {
-    int size;
+    off_t size;
     int filecount = 0;
     DEBUG(D_transport)
       debug_printf("quota checks on directory %s\n", check_path);
@@ -2573,8 +2589,8 @@
   {
   DEBUG(D_transport)
     {
-    debug_printf("Exim quota = %d old size = %d this message = %d "
-      "(%sincluded)\n", ob->quota_value, mailbox_size, message_size,
+    debug_printf("Exim quota = %s old size = %s this message = %d "
+      "(%sincluded)\n", offtostr(ob->quota_value), offtostr(mailbox_size), message_size,
       ob->quota_is_inclusive? "" : "not ");
     debug_printf("  file count quota = %d count = %d\n",
       ob->quota_filecount_value, mailbox_filecount);
@@ -2759,8 +2775,8 @@
   if (ob->quota_warn_threshold_is_percent)
     threshold = (int)(((double)ob->quota_value * threshold) / 100);
   DEBUG(D_transport)
-    debug_printf("quota = %d threshold = %d old size = %d message size = %d\n",
-      ob->quota_value, threshold, mailbox_size, message_size);
+    debug_printf("quota = %s threshold = %s old size = %s message size = %d\n",
+      offtostr(ob->quota_value), offtostr(threshold), offtostr(mailbox_size), message_size);
   if (mailbox_size <= threshold && mailbox_size + message_size > threshold)
     addr->special_action = SPECIAL_WARN;


--- src/transports/appendfile.h.orig    2005-04-28 15:49:15.000000000 +0200
+++ src/transports/appendfile.h    2005-04-28 17:10:26.000000000 +0200
@@ -32,7 +32,7 @@
   uschar *file_format;
   int   mailbox_size_value;
   int   mailbox_filecount_value;
-  int   quota_value;
+  off_t quota_value;
   int   quota_filecount_value;
   int   quota_warn_threshold_value;
   int   mode;
@@ -92,6 +92,6 @@


/* Function that is shared with tf_maildir.c */

-extern int check_dir_size(uschar *, int *, const pcre *);
+extern off_t check_dir_size(uschar *, int *, const pcre *);

/* End of transports/appendfile.h */