ph10 2004/11/17 14:32:25 GMT
Modified files:
exim-doc/doc-txt ChangeLog NewStuff
exim-src/src expand.c functions.h receive.c
exim-test-orig/AutoTest/scripts 571
Log:
Added $spool_size, $log_size, $spool_inodes, $log_inodes.
Revision Changes Path
1.29 +5 -0 exim/exim-doc/doc-txt/ChangeLog
1.10 +19 -0 exim/exim-doc/doc-txt/NewStuff
1.4 +23 -1 exim/exim-src/src/expand.c
1.3 +1 -0 exim/exim-src/src/functions.h
1.4 +131 -99 exim/exim-src/src/receive.c
1.3 +1 -1 exim/exim-test-orig/AutoTest/scripts/571
Index: ChangeLog
===================================================================
RCS file: /home/cvs/exim/exim-doc/doc-txt/ChangeLog,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -r1.28 -r1.29
--- ChangeLog 12 Nov 2004 16:54:55 -0000 1.28
+++ ChangeLog 17 Nov 2004 14:32:25 -0000 1.29
@@ -1,4 +1,4 @@
-$Cambridge: exim/exim-doc/doc-txt/ChangeLog,v 1.28 2004/11/12 16:54:55 ph10 Exp $
+$Cambridge: exim/exim-doc/doc-txt/ChangeLog,v 1.29 2004/11/17 14:32:25 ph10 Exp $
Change log file for Exim from version 4.21
-------------------------------------------
@@ -116,6 +116,11 @@
30. Exim went into a mad DNS loop when attempting to do a callout where the
host was specified on an smtp transport, and looking it up yielded more
than one IP address.
+
+31. Re-factored the code for checking spool and log partition space into a
+ function that finds that data and another that does the check. The former
+ is then used to implement four new variables: $spool_space, $log_space,
+ $spool_inodes, and $log_inodes.
Exim version 4.43
Index: NewStuff
===================================================================
RCS file: /home/cvs/exim/exim-doc/doc-txt/NewStuff,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- NewStuff 11 Nov 2004 11:40:36 -0000 1.9
+++ NewStuff 17 Nov 2004 14:32:25 -0000 1.10
@@ -1,4 +1,4 @@
-$Cambridge: exim/exim-doc/doc-txt/NewStuff,v 1.9 2004/11/11 11:40:36 ph10 Exp $
+$Cambridge: exim/exim-doc/doc-txt/NewStuff,v 1.10 2004/11/17 14:32:25 ph10 Exp $
New Features in Exim
--------------------
@@ -70,6 +70,25 @@
9. $host_address is now set to the target address during the checking of
ignore_target_hosts.
+10. There are four new variables called $spool_space, $log_space,
+ $spool_inodes, and $log_inodes. The first two contain the amount of free
+ space in the disk partitions where Exim has its spool directory and log
+ directory, respectively. (When these are in the same partition, the values
+ will, of course, be the same.) The second two variables contain the numbers
+ of free inodes in the respective partitions.
+
+ NOTE: Because disks can nowadays be very large, the values in the space
+ variables are in kilobytes rather than in bytes. Thus, for example, to
+ check in an ACL that there is at least 50M free on the spool, you would
+ write:
+
+ condition = ${if > {$spool_space}{50000}{yes}{no}}
+
+ The values are recalculated whenever any of these variables is referenced.
+ If the relevant file system does not have the concept of inodes, the value
+ of those variables is -1. If the operating system does not have the ability
+ to find the amount of free space (only true for experimental systems), the
+ space value is -1.
Version 4.43
Index: expand.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/expand.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- expand.c 5 Nov 2004 16:53:28 -0000 1.3
+++ expand.c 17 Nov 2004 14:32:25 -0000 1.4
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/expand.c,v 1.3 2004/11/05 16:53:28 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/expand.c,v 1.4 2004/11/17 14:32:25 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -283,7 +283,9 @@
vtype_reply, /* value not used; get reply from headers */
vtype_pid, /* value not used; result is pid */
vtype_host_lookup, /* value not used; get host name */
- vtype_load_avg /* value not used; result is int from os_getloadavg */
+ vtype_load_avg, /* value not used; result is int from os_getloadavg */
+ vtype_pspace, /* partition space; value is T/F for spool/log */
+ vtype_pinodes /* partition inodes; value is T/F for spool/log */
};
/* This table must be kept in alphabetical order. */
@@ -352,6 +354,8 @@
{ "local_user_gid", vtype_gid, &local_user_gid },
{ "local_user_uid", vtype_uid, &local_user_uid },
{ "localhost_number", vtype_int, &host_number },
+ { "log_inodes", vtype_pinodes, (void *)FALSE },
+ { "log_space", vtype_pspace, (void *)FALSE },
{ "mailstore_basename", vtype_stringptr, &mailstore_basename },
{ "message_age", vtype_int, &message_age },
{ "message_body", vtype_msgbody, &message_body },
@@ -421,6 +425,8 @@
{ "sn8", vtype_filter_int, &filter_sn[8] },
{ "sn9", vtype_filter_int, &filter_sn[9] },
{ "spool_directory", vtype_stringptr, &spool_directory },
+ { "spool_inodes", vtype_pinodes, (void *)TRUE },
+ { "spool_space", vtype_pspace, (void *)TRUE },
{ "thisaddress", vtype_stringptr, &filter_thisaddress },
{ "tls_certificate_verified", vtype_int, &tls_certificate_verified },
{ "tls_cipher", vtype_stringptr, &tls_cipher },
@@ -1310,6 +1316,22 @@
s[ptr] = 0; /* string_cat() leaves room */
}
return s;
+
+ case vtype_pspace:
+ {
+ int inodes;
+ sprintf(CS var_buffer, "%d",
+ receive_statvfs((BOOL)(var_table[middle].value), &inodes));
+ }
+ return var_buffer;
+
+ case vtype_pinodes:
+ {
+ int inodes;
+ (void) receive_statvfs((BOOL)(var_table[middle].value), &inodes);
+ sprintf(CS var_buffer, "%d", inodes);
+ }
+ return var_buffer;
}
}
Index: functions.h
===================================================================
RCS file: /home/cvs/exim/exim-src/src/functions.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- functions.h 4 Nov 2004 12:19:48 -0000 1.2
+++ functions.h 17 Nov 2004 14:32:25 -0000 1.3
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/functions.h,v 1.2 2004/11/04 12:19:48 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/functions.h,v 1.3 2004/11/17 14:32:25 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -180,6 +180,7 @@
extern BOOL receive_check_fs(int);
extern BOOL receive_check_set_sender(uschar *);
extern BOOL receive_msg(BOOL);
+extern int receive_statvfs(BOOL, int *);
extern void receive_swallow_smtp(void);
extern BOOL regex_match_and_setup(const pcre *, uschar *, int, int);
extern const pcre *regex_must_compile(uschar *, BOOL, BOOL);
Index: receive.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/receive.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- receive.c 19 Oct 2004 11:04:26 -0000 1.3
+++ receive.c 17 Nov 2004 14:32:25 -0000 1.4
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/receive.c,v 1.3 2004/10/19 11:04:26 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/receive.c,v 1.4 2004/11/17 14:32:25 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -92,90 +92,55 @@
/*************************************************
-* Check space on spool and log partitions *
+* Read space info for a partition *
*************************************************/
-/* This function is called before accepting a message; if any thresholds are
-set, it checks them. If a message_size is supplied, it checks that there is
-enough space for that size plus the threshold - i.e. that the message won't
-reduce the space to the threshold. Not all OS have statvfs(); for those that
-don't, this function always returns TRUE. For some OS the old function and
-struct name statfs is used; that is handled by a macro, defined in exim.h.
+/* This function is called by receive_check_fs() below, and also by string
+expansion for variables such as $spool_space. The field names for the statvfs
+structure are macros, because not all OS have F_FAVAIL and it seems tidier to
+have macros for F_BAVAIL and F_FILES as well. Some kinds of file system do not
+have inodes, and they return -1 for the number available.
-Arguments:
- msg_size the (estimated) size of an incoming message
+Later: It turns out that some file systems that do not have the concept of
+inodes return 0 rather than -1. Such systems should also return 0 for the total
+number of inodes, so we require that to be greater than zero before returning
+an inode count.
-Returns: FALSE if there isn't enough space, or if the information cannot
- be obtained
- TRUE if no check was done or there is enough space
+Arguments:
+ isspool TRUE for spool partition, FALSE for log partition
+ inodeptr address of int to receive inode count; -1 if there isn't one
+
+Returns: available on-root space, in kilobytes
+ -1 for log partition if there isn't one
+
+All values are -1 if the STATFS functions are not available.
*/
-BOOL
-receive_check_fs(int msg_size)
+int
+receive_statvfs(BOOL isspool, int *inodeptr)
{
#ifdef HAVE_STATFS
-BOOL rc = TRUE;
struct STATVFS statbuf;
+uschar *path;
+uschar *name;
+uschar buffer[1024];
-memset(&statbuf, 0, sizeof(statbuf));
+/* The spool directory must always exist. */
-/* The field names are macros, because not all OS have F_FAVAIL and it seems
-tidier to have macros for F_BAVAIL and F_FILES as well. Some kinds of file
-server do not have inodes, and they return -1 for the number available, so we
-do the check only when this field is non-negative.
-
-Later: It turns out that some file systems that do not have the concept of
-inodes return 0 rather than -1. Such systems should also return 0 for the total
-number of inodes, so we require that to be greater than zero before doing the
-test. */
-
-if (check_spool_space > 0 || msg_size > 0 || check_spool_inodes > 0)
+if (isspool)
{
- if (STATVFS(CS spool_directory, &statbuf) != 0)
- {
- log_write(0, LOG_MAIN|LOG_PANIC, "cannot accept message: failed to stat "
- "spool directory %s: %s", spool_directory, strerror(errno));
- smtp_closedown(US"spool directory problem");
- exim_exit(EXIT_FAILURE);
- }
-
- /* check_spool_space is held in K because disks are getting huge */
-
- if (statbuf.F_BAVAIL < (unsigned long)
- ((((double)check_spool_space) * 1024.0 + (double)msg_size) /
- (double)statbuf.F_FRSIZE)
- ||
- (statbuf.F_FILES > 0 &&
- statbuf.F_FAVAIL >= 0 &&
- statbuf.F_FAVAIL < check_spool_inodes))
- rc = FALSE;
-
- DEBUG(D_receive)
- debug_printf("spool directory %s space = %d blocks; inodes = %d; "
- "check_space = %dK (%d blocks); inodes = %d; msg_size = %d (%d blocks)\n",
- spool_directory, (int)statbuf.F_BAVAIL, (int)statbuf.F_FAVAIL,
- check_spool_space,
- (int)(((double)check_spool_space * 1024.0) / (double)statbuf.F_FRSIZE),
- check_spool_inodes, msg_size, (int)(msg_size / statbuf.F_FRSIZE));
-
- if (!rc)
- {
- log_write(0, LOG_MAIN, "spool directory space check failed: space=%d "
- "inodes=%d", (int)statbuf.F_BAVAIL, (int)statbuf.F_FAVAIL);
- return FALSE;
- }
- }
-
+ path = spool_directory;
+ name = US"spool";
+ }
+
/* Need to cut down the log file path to the directory, and to ignore any
appearance of "syslog" in it. */
-if (check_log_space > 0 || check_log_inodes > 0)
+else
{
- uschar *path;
int sep = ':'; /* Not variable - outside scripts use */
- uschar *cp;
uschar *p = log_file_path;
- uschar buffer[1024];
+ name = US"log";
/* An empty log_file_path means "use the default". This is the same as an
empty item in a list. */
@@ -186,50 +151,117 @@
if (Ustrcmp(path, "syslog") != 0) break;
}
- if (path == NULL) return TRUE; /* No log files, so no problem */
+ if (path == NULL) /* No log files */
+ {
+ *inodeptr = -1;
+ return -1;
+ }
+
+ /* An empty string means use the default, which is in the spool directory.
+ But don't just use the spool directory, as it is possible that the log
+ subdirectory has been symbolically linked elsewhere. */
- /* An empty string means use the default */
+ if (path[0] == 0)
+ {
+ sprintf(CS buffer, CS"%s/log", CS spool_directory);
+ path = buffer;
+ }
+ else
+ {
+ uschar *cp;
+ if ((cp = Ustrrchr(path, '/')) != NULL) *cp = 0;
+ }
+ }
+
+/* We now have the patch; do the business */
- if (path[0] == 0)
- path = string_sprintf("%s/log/%%slog", spool_directory);
+memset(&statbuf, 0, sizeof(statbuf));
- if ((cp = Ustrrchr(path, '/')) == NULL)
- {
- DEBUG(D_receive) debug_printf("cannot find slash in %s\n", path);
- return FALSE;
- }
- *cp = 0;
+if (STATVFS(CS path, &statbuf) != 0)
+ {
+ log_write(0, LOG_MAIN|LOG_PANIC, "cannot accept message: failed to stat "
+ "%s directory %s: %s", name, spool_directory, strerror(errno));
+ smtp_closedown(US"spool or log directory problem");
+ exim_exit(EXIT_FAILURE);
+ }
+
+*inodeptr = (statbuf.F_FILES > 0)? statbuf.F_FAVAIL : -1;
- if (STATVFS(CS path, &statbuf) != 0)
- {
- log_write(0, LOG_MAIN|LOG_PANIC, "cannot accept message: failed to stat "
- "log directory %s: %s", path, strerror(errno));
- smtp_closedown(US"log directory problem");
- exim_exit(EXIT_FAILURE);
- }
+/* Disks are getting huge. Take care with computing the size in kilobytes. */
+
+return (int)(((double)statbuf.F_BAVAIL * (double)statbuf.F_FRSIZE)/1024.0);
+
+/* Unable to find partition sizes in this environment. */
+
+#else
+*inodeptr = -1;
+return -1;
+#endif
+}
- if (statbuf.F_BAVAIL < (unsigned long)
- (((double)check_log_space * 1024.0) / (double)statbuf.F_FRSIZE)
- ||
- statbuf.F_FAVAIL < check_log_inodes) rc = FALSE;
- DEBUG(D_receive)
- debug_printf("log directory %s space = %d blocks; inodes = %d; "
- "check_space = %dK (%d blocks); inodes = %d\n",
- path, (int)statbuf.F_BAVAIL, (int)statbuf.F_FAVAIL,
- check_log_space,
- (int)(((double)check_log_space * 1024.0) / (double)statbuf.F_FRSIZE),
- check_log_inodes);
- if (!rc)
- {
- log_write(0, LOG_MAIN, "log directory space check failed: space=%d "
- "inodes=%d", (int)statbuf.F_BAVAIL, (int)statbuf.F_FAVAIL);
+
+/*************************************************
+* Check space on spool and log partitions *
+*************************************************/
+
+/* This function is called before accepting a message; if any thresholds are
+set, it checks them. If a message_size is supplied, it checks that there is
+enough space for that size plus the threshold - i.e. that the message won't
+reduce the space to the threshold. Not all OS have statvfs(); for those that
+don't, this function always returns TRUE. For some OS the old function and
+struct name statfs is used; that is handled by a macro, defined in exim.h.
+
+Arguments:
+ msg_size the (estimated) size of an incoming message
+
+Returns: FALSE if there isn't enough space, or if the information cannot
+ be obtained
+ TRUE if no check was done or there is enough space
+*/
+
+BOOL
+receive_check_fs(int msg_size)
+{
+int space, inodes;
+
+if (check_spool_space > 0 || msg_size > 0 || check_spool_inodes > 0)
+ {
+ space = receive_statvfs(TRUE, &inodes);
+
+ DEBUG(D_receive)
+ debug_printf("spool directory space = %dK inodes = %d "
+ "check_space = %dK inodes = %d msg_size = %d\n",
+ space, inodes, check_spool_space, check_spool_inodes, msg_size);
+
+ if ((space >= 0 && space < check_spool_space) ||
+ (inodes >= 0 && inodes < check_spool_inodes))
+ {
+ log_write(0, LOG_MAIN, "spool directory space check failed: space=%d "
+ "inodes=%d", space, inodes);
return FALSE;
}
}
-#endif
+if (check_log_space > 0 || check_log_inodes > 0)
+ {
+ space = receive_statvfs(FALSE, &inodes);
+
+ DEBUG(D_receive)
+ debug_printf("log directory space = %dK inodes = %d "
+ "check_space = %dK inodes = %d\n",
+ space, inodes, check_log_space, check_log_inodes);
+
+ if ((space >= 0 && space < check_log_space) ||
+ (inodes >= 0 && inodes < check_log_inodes))
+ {
+ log_write(0, LOG_MAIN, "log directory space check failed: space=%d "
+ "inodes=%d", space, inodes);
+ return FALSE;
+ }
+ }
+
return TRUE;
}
Index: 571
===================================================================
RCS file: /home/cvs/exim/exim-test-orig/AutoTest/scripts/571,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- 571 19 Oct 2004 11:04:26 -0000 1.2
+++ 571 17 Nov 2004 14:32:25 -0000 1.3
@@ -186,7 +186,7 @@
exim -DSERVER=server -DSUBMISSION_OPTIONS=/domain=a.b.c/sender_retain -bd -oX 1225
****
0
-sleep 1
+sleep 2
****
0
client 127.0.0.1 1225