From 4123608771a6dd6a0e623124009eafccd7cddb93 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Wed, 10 Sep 2008 00:07:44 +0200 Subject: [PATCH] Devised simple log rotation to prevent per-user sieve processing logs to grow indefinitely. --- TODO | 1 - src/lib-sieve/sieve-error.c | 53 ++++++++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/TODO b/TODO index 6e3cbf3eb..971b040e8 100644 --- a/TODO +++ b/TODO @@ -5,7 +5,6 @@ Next (in order of descending priority/precedence): - Variables: dump variable identifiers in stead of storage indexes - Improve argument errors * Make sure cmusieve can be replaced seamlessly with the new plugin. - - Add simple log rotation to script error log. * Fix/Report issues listed in 'doc/rfc/RFC Controversy.txt' * ## MAKE A FIRST RELEASE (0.1.x) ## diff --git a/src/lib-sieve/sieve-error.c b/src/lib-sieve/sieve-error.c index 852f5a744..ce2a2bc70 100644 --- a/src/lib-sieve/sieve-error.c +++ b/src/lib-sieve/sieve-error.c @@ -24,6 +24,9 @@ "internal error occurred: refer to server log for more information." #define CRITICAL_MSG_STAMP CRITICAL_MSG " [%Y-%m-%d %H:%M:%S]" +/* Logfile error handler will rotate log when it exceeds 10k bytes */ +#define LOGFILE_MAX_SIZE (10 * 1024) + /* * Utility */ @@ -380,24 +383,68 @@ static void sieve_logfile_start(struct sieve_logfile_ehandler *ehandler) { int fd; struct ostream *ostream = NULL; + struct stat st; struct tm *tm; char buf[256]; time_t now; + /* Open the logfile */ + fd = open(ehandler->logfile, O_CREAT | O_APPEND | O_WRONLY, 0600); if (fd == -1) { sieve_sys_error("failed to open logfile %s (logging to STDERR): %m", ehandler->logfile); fd = STDERR_FILENO; + } else { + /* fd_close_on_exec(fd, TRUE); Necessary? */ + + /* Stat the log file to obtain size information */ + if ( fstat(fd, &st) != 0 ) { + sieve_sys_error( + "failed to fstat opened logfile %s (logging to STDERR): %m", + ehandler->logfile); + + if ( close(fd) < 0 ) { + sieve_sys_error("close(fd) failed for logfile '%s': %m", + ehandler->logfile); + } + + fd = STDERR_FILENO; + } + + /* Rotate log when it has grown too large */ + if ( st.st_size >= LOGFILE_MAX_SIZE ) { + const char *rotated; + + /* Close open file */ + if ( close(fd) < 0 ) { + sieve_sys_error("close(fd) failed for logfile '%s': %m", + ehandler->logfile); + } + + /* Rotate logfile */ + rotated = t_strconcat(ehandler->logfile, ".0", NULL); + if ( rename(ehandler->logfile, rotated) < 0 ) { + sieve_sys_error( + "failed to rename logfile %s to %s: %m", + ehandler->logfile, rotated); + } + + /* Open clean logfile (overwrites existing if rename() failed earlier) */ + fd = open(ehandler->logfile, O_CREAT | O_WRONLY, 0600); + if (fd == -1) { + sieve_sys_error("failed to open logfile %s (logging to STDERR): %m", + ehandler->logfile); + fd = STDERR_FILENO; + } + } } - /* else - fd_close_on_exec(fd, TRUE); Necessary? */ ostream = o_stream_create_fd(fd, 0, FALSE); if ( ostream == NULL ) { /* Can't we do anything else in this most awkward situation? */ sieve_sys_error("failed to open log stream on open file %s: " - "normal messages will not be logged!", ehandler->logfile); + "non-critical messages will not be logged!", ehandler->logfile); } ehandler->fd = fd; -- GitLab