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]