qmail-1.03-quotas-1.1.patch
Jan 3, 2000
This patch to qmail-1.03 modifies the way qmail-local treats a 'quota
exceeded' error when writing to a maildir.
The virgin code as distributed by DJB treats this as a 'temporary
error on maildir' and leaves the message in the queue for later
delivery retries. The modified code treats it as a permanent error
and immediately returns the message to the sender.
This allows you use the standard unix file system quota mechanism to
enforce per-uid limits on either the number of files (inodes) in that
uid's maildir(s) or the total size of all files (blocks) in the
maildir(s), or both, without leaving yourself (as) exposed to
potential denial of service by running out of space for the qmail
queue area.
Please let me know if you find this useful (or not). I am happy to
receive bug reports as well as other comments.
Thanks,
-- Jeff Hayward
j.hayward@ots.utexas.edu
*** qmail-1.03/qmail-local.c Mon Jan 3 12:15:42 2000
--- qmail-local.c Tue Dec 21 19:41:39 1999
***************
*** 41,46 ****
--- 41,49 ----
void temp_qmail(fn) char *fn;
{ strerr_die5x(111,"Unable to open ",fn,": ",error_str(errno),". (#4.3.0)"); }
+ char *overquota =
+ "Recipient's mailbox is full, message returned to sender. (#5.2.2)";
+
int flagdoit;
int flag99;
***************
*** 110,116 ****
alarm(86400);
fd = open_excl(fntmptph);
! if (fd == -1) _exit(1);
substdio_fdbuf(&ss,read,0,buf,sizeof(buf));
substdio_fdbuf(&ssout,write,fd,outbuf,sizeof(outbuf));
--- 113,124 ----
alarm(86400);
fd = open_excl(fntmptph);
! if (fd == -1) {
! if (errno == error_dquot)
! _exit(5);
! else
! _exit(1);
! }
substdio_fdbuf(&ss,read,0,buf,sizeof(buf));
substdio_fdbuf(&ssout,write,fd,outbuf,sizeof(outbuf));
***************
*** 131,137 ****
/* if it was error_exist, almost certainly successful; i hate NFS */
tryunlinktmp(); _exit(0);
! fail: tryunlinktmp(); _exit(1);
}
/* end child process */
--- 139,150 ----
/* if it was error_exist, almost certainly successful; i hate NFS */
tryunlinktmp(); _exit(0);
! fail:
! if (errno == error_dquot) {
! tryunlinktmp(); _exit(5);
! } else {
! tryunlinktmp(); _exit(1);
! }
}
/* end child process */
***************
*** 162,167 ****
--- 175,181 ----
case 2: strerr_die1x(111,"Unable to chdir to maildir. (#4.2.1)");
case 3: strerr_die1x(111,"Timeout on maildir delivery. (#4.3.0)");
case 4: strerr_die1x(111,"Unable to read message. (#4.3.0)");
+ case 5: strerr_die1x(100,overquota);
default: strerr_die1x(111,"Temporary error on maildir delivery. (#4.3.0)");
}
}
***************
*** 221,227 ****
return;
writeerrs:
! strerr_warn5("Unable to write ",fn,": ",error_str(errno),". (#4.3.0)",0);
if (flaglocked) seek_trunc(fd,pos);
close(fd);
_exit(111);
--- 235,246 ----
return;
writeerrs:
! if (errno == error_dquot) {
! if (flaglocked) seek_trunc(fd,pos);
! close(fd);
! strerr_die1x(100,overquota);
! } else
! strerr_warn5("Unable to write ",fn,": ",error_str(errno),". (#4.3.0)",0);
if (flaglocked) seek_trunc(fd,pos);
close(fd);
_exit(111);
*** qmail-1.03/error.h Mon Jan 3 12:15:42 2000
--- error.h Tue Sep 15 11:52:14 1998
***************
*** 16,21 ****
--- 16,22 ----
extern int error_pipe;
extern int error_perm;
extern int error_acces;
+ extern int error_dquot;
extern char *error_str();
extern int error_temp();
*** qmail-1.03/error.c Mon Jan 3 12:15:42 2000
--- error.c Tue Sep 15 11:53:29 1998
***************
*** 93,95 ****
--- 93,102 ----
#else
-13;
#endif
+
+ int error_dquot =
+ #ifdef EDQUOT
+ EDQUOT;
+ #else
+ -14;
+ #endif