Chris,
I looked at the int user_over_quota(char *maildir, char *quota)
function which is called in vdelivermail.c to check the quota. From what I
can tell this function calls off_t check_quota(char *maildir) which returns
0 if the .current_size file does not exist or it deliver the contents of
this file if it does exist. This file then gets updated by the
update_quota(off_t) which is called by user_over_quota() just before it
delivers the message. update_quota() adds the size of the message being
delivered. If check_quota returns a value that would put the user over
quota then off_t recalc_quota(char *maildir) is called. recalc_quota()
recalculates the quota by adding up the size of the files in maildir then
writing it to the .current_size file and returning this size.
If I'v got that logic correct then it should work. I looked at the
implementation and didn't see any obvious mistakes. The logic is a little
fuzzy because the quota only gets reduced when the user goes over quota. Of
course an old or dirty size can be returned from check_quota(). But this is
ok because in this case the quota is double checked and made consistent by
the call to recalc_quota(). Its also the only feasible way to do it since
vdelivermail never knows about when or what or how big a file is when its
deleted because that is only taking place in the pop or imap server. Its
also good because it spends little time calculating disk usage under most
conditions which is a I/O expensive task.
Where do you think the error is occuring?
Am I missing something?
Can you produce an error by setting up a mailbox and then sending several
files to it so it is close to its quota. Then delete one of the files and
then try and deliver one that should be under quota but only if the quota is
being re calculated properly by recalc_quota() ?
What kind of logging/message are you interested in adding when a user has a
mail bounced because of quota? To syslog? To mysql?
-David Wartell
ActionWeb Services
[EMAIL PROTECTED]
----- Original Message -----
From: cbunnell
To: David Wartell
Cc: [EMAIL PROTECTED]
Sent: Monday, July 02, 2001 7:06 PM
Subject: Re: patch to vpopmail.c to fix Solaris unlink() bug
Good job on this patch David!
I noticed the same behavior, but didn't put 2 and 2 together quite as well
as you did...
On a different note, in regard to bugs, have you noticed that the
".current_size" code in vdelivermail is broken? .current_size never reduces
as you delete mail. It just keeps getting bigger and bigger....
I was working on a "user over quota" message when I discovered it. Made my
code a real pain in the ass to figure out. I kept blaming my code for some
of the things I was seeing happen. I finally realized that even the "stock"
code was broken.
I'm working on it, but I'm not much of a C programmer.. I'm struggling
pretty hard with this stuff. Maybe you'd be interested in taking a look at
it? (Now that I've pointed it out, you'd probably look into it anyway. :)
Chris Bunnell
----- Original Message -----
From: "David Wartell" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Monday, July 02, 2001 12:05 PM
Subject: patch to vpopmail.c to fix Solaris unlink() bug
> Here is a patch to fix a bug that was found in int vdelfiles( char *) in
vpopmail.c. The problem is that vdelfiles assumes that
> calling unlink() on a directory will return an error. This is true on
Linux but is NOT true on Solaris. What the vdelfiles() code
> does on Solaris without this patch on Solaris is unlink the given
directory from its parent which leaves the file system corrupted
> and the disk space and inodes used even though the entry looks like it is
deleted. The patch should make the code more portable (at
> least across Linux AND Solaris).
>
> Here is a sequence of commands which repoduce the error on a Solaris host.
The commands were run on a fresh install of vpopmail
> 4.10.24, although 4.10.26 and earlier produce the same error on Solaris.
The patch is known to patch cleanly against 4.10.24 and
> 4.10.26
>
> --------------------------testing reproducing the
error---------------------------
> Notice the link count for the domains directory.
> apollo:/var/vpopmail # ls -l -d domains
> drwx------ 2 vpopmail vchkpw 512 Jun 29 14:51 domains/
>
> I add a domain and of course the link count goes up as expected because a
directory was added to domains
> apollo:/var/vpopmail # bin/vadddomain foo.com 2782y2
> apollo:/var/vpopmail # ls -l -d domains
> drwx------ 3 vpopmail vchkpw 512 Jun 29 14:52 domains/
>
> I add a second domain and the link count of domain goes up again as
expected
> apollo:/var/vpopmail # bin/vadddomain foo2.com 2782y2
> apollo:/var/vpopmail # ls -l -d domains
> drwx------ 4 vpopmail vchkpw 512 Jun 29 14:52 domains/
>
> Now I remove a domain and the link count of domains does NOT go down!
This means the disk space and inodes are still being used.
> apollo:/var/vpopmail # bin/vdeldomain foo2.com
> apollo:/var/vpopmail # ls -l -d domains
> drwx------ 4 vpopmail vchkpw 512 Jun 29 14:52 domains/
> apollo:/var/vpopmail # ls -l domains
> total 1
> drwx------ 3 vpopmail vchkpw 512 Jun 29 14:52 foo.com/
> apollo:/var/vpopmail #
>
>
> ----------------the
patch------------------------------------------------------
> diff vpopmail.c ../vpopmail-4.10.24.dist/vpopmail.c
>
> 425,434c425,448
> < /* try to unlink the file, this will fail on directories
> < * but it will succeed on symbolic links, because it a
> < * file ;) this is how we erase an aliased domain from
> < * the file system.
> < * On success, return success
> < */
> < if ( unlink(dir) == 0 ) {
> < /* return success */
> < return(0);
> < }
> ---
> > /* Modified By David Wartell [EMAIL PROTECTED] to work with
Solaris.
> > * Unlike Linux, Solaris will NOT return error when unlink() is called
on a
> > * directory. A correct implementation to support Linux & Solaris is
to test
> > * to see if the file is a directory. If it is not a directory unlink()
it.
> > * If unlink() returns an error return error.
> > */
> >
> > if (lstat(dir, &statbuf) == 0) {
> > // if dir is not a directory unlink it
> > if ( !( S_ISDIR(statbuf.st_mode) ) ) {
> > if ( unlink(dir) == 0 ) {
> > /* return success we deleted the file */
> > return(0);
> > }
> > else {
> > /* error, return error to calling function, we couldn't
unlink the file */
> > return(-1);
> > }
> > }
> >
> > } else {
> > /* error, return error to calling function, we couldn't lstat
the file */
> > return(-1);
> > }
>
> -David Wartell
> ActionWeb Services
> [EMAIL PROTECTED]
>
>