From eab4a5f0b33286a5fbf31b4e73367a949da5db6b Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Nov 03 2016 06:19:42 +0000 Subject: import logrotate-3.8.6-12.el7 --- diff --git a/SOURCES/logrotate-3.8.6-diagnostic.patch b/SOURCES/logrotate-3.8.6-diagnostic.patch new file mode 100644 index 0000000..7aaf844 --- /dev/null +++ b/SOURCES/logrotate-3.8.6-diagnostic.patch @@ -0,0 +1,690 @@ +From e804f560400d329f25d401064a4b9fb1826ee242 Mon Sep 17 00:00:00 2001 +From: jkaluza +Date: Mon, 23 Feb 2015 14:52:53 +0000 +Subject: [PATCH 1/7] Add support for %H dateformat [czchen] + +Upstream-commit: 9edfa9f40fa4aa20b010c829d10eedb3e1bf985b +Signed-off-by: Kamil Dudka +--- + logrotate.8 | 9 +++++---- + logrotate.c | 1 + + test/test | 14 ++++++++++++++ + test/test-config.61.in | 8 ++++++++ + 4 files changed, 28 insertions(+), 4 deletions(-) + create mode 100644 test/test-config.61.in + +diff --git a/logrotate.8 b/logrotate.8 +index 2cd2370..89dd82a 100644 +--- a/logrotate.8 ++++ b/logrotate.8 +@@ -238,10 +238,11 @@ the \fBdateformat\fR and \fBdateyesterday\fR options. + .TP + \fBdateformat\fR \fIformat_string\fR + Specify the extension for \fBdateext\fR using the notation similar to +-\fBstrftime\fR(3) function. Only %Y %m %d and %s specifiers are allowed. +-The default value is \-%Y%m%d. Note that also the character separating log +-name from the extension is part of the dateformat string. The system clock +-must be set past Sep 9th 2001 for %s to work correctly. ++\fBstrftime\fR(3) function. Only %Y %m %d %H and %s specifiers are allowed. ++The default value is \-%Y%m%d except hourly, which uses \-%Y%m%d%H as default ++value. Note that also the character separating log name from the extension is ++part of the dateformat string. The system clock must be set past Sep 9th 2001 ++for %s to work correctly. + Note that the datestamps generated by this format must be lexically sortable + (i.e., first the year, then the month then the day. e.g., 2001/12/01 is ok, + but 01/12/2001 is not, since 01/11/2002 would sort lower while it is later). +diff --git a/logrotate.c b/logrotate.c +index c81c6cd..7bb3484 100644 +--- a/logrotate.c ++++ b/logrotate.c +@@ -1033,6 +1033,7 @@ int prerotateSingleLog(struct logInfo *log, int logNum, struct logState *state, + j += 10; /* strlen("[0-9][0-9]") */ + case 'm': + case 'd': ++ case 'H': + strncat(dext_pattern, "[0-9][0-9]", + sizeof(dext_pattern) - strlen(dext_pattern)); + j += 10; +diff --git a/test/test b/test/test +index 6a86e39..3363d42 100755 +--- a/test/test ++++ b/test/test +@@ -1517,4 +1517,18 @@ if [ $? == 0 ]; then + exit 3 + fi + ++cleanup 61 ++ ++# ------------------------------- Test 61 ------------------------------------ ++preptest test.log 61 1 0 ++ ++$RLR test-config.61 --force ++ ++DATESTRING=$(/bin/date +%Y-%m-%d-%H) ++ ++checkoutput < +Date: Wed, 1 Apr 2015 12:51:50 +0000 +Subject: [PATCH 2/7] Show better message when log does not need rotating + +Upstream-commit: 3d91c5bed7a1c178d9b3499f0adc545ebac9f281 +Signed-off-by: Kamil Dudka +--- + logrotate.c | 47 ++++++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 44 insertions(+), 3 deletions(-) + +diff --git a/logrotate.c b/logrotate.c +index 7bb3484..32d26b9 100644 +--- a/logrotate.c ++++ b/logrotate.c +@@ -864,6 +864,10 @@ int findNeedRotating(struct logInfo *log, int logNum, int force) + } + else if (log->criterium == ROT_SIZE) { + state->doRotate = (sb.st_size >= log->threshhold); ++ if (!state->doRotate) { ++ message(MESS_DEBUG, " log does not need rotating " ++ "(log size is below the 'size' threshold)\n"); ++ } + } else if (mktime(&state->lastRotated) - mktime(&now) > (25 * 3600)) { + /* 25 hours allows for DST changes as well as geographical moves */ + message(MESS_ERROR, +@@ -886,36 +890,75 @@ int findNeedRotating(struct logInfo *log, int logNum, int force) + ((mktime(&now) - + mktime(&state->lastRotated)) > + (7 * 24 * 3600))); ++ if (!state->doRotate) { ++ message(MESS_DEBUG, " log does not need rotating " ++ "(log has been rotated at %d-%d-%d %d:%d, " ++ "that is not week ago yet)\n", state->lastRotated.tm_year, ++ state->lastRotated.tm_mon, state->lastRotated.tm_mday, ++ state->lastRotated.tm_hour, state->lastRotated.tm_min); ++ } + break; + case ROT_HOURLY: + state->doRotate = ((now.tm_hour != state->lastRotated.tm_hour) || + (now.tm_mday != state->lastRotated.tm_mday) || + (now.tm_mon != state->lastRotated.tm_mon) || + (now.tm_year != state->lastRotated.tm_year)); ++ if (!state->doRotate) { ++ message(MESS_DEBUG, " log does not need rotating " ++ "(log has been rotated at %d-%d-%d %d:%d, " ++ "that is not hour ago yet)\n", state->lastRotated.tm_year, ++ state->lastRotated.tm_mon, state->lastRotated.tm_mday, ++ state->lastRotated.tm_hour, state->lastRotated.tm_min); ++ } + break; + case ROT_DAYS: + /* FIXME: only days=1 is implemented!! */ + state->doRotate = ((now.tm_mday != state->lastRotated.tm_mday) || + (now.tm_mon != state->lastRotated.tm_mon) || + (now.tm_year != state->lastRotated.tm_year)); ++ if (!state->doRotate) { ++ message(MESS_DEBUG, " log does not need rotating " ++ "(log has been rotated at %d-%d-%d %d:%d, " ++ "that is not day ago yet)\n", state->lastRotated.tm_year, ++ state->lastRotated.tm_mon, state->lastRotated.tm_mday, ++ state->lastRotated.tm_hour, state->lastRotated.tm_min); ++ } + break; + case ROT_MONTHLY: + /* rotate if the logs haven't been rotated this month or + this year */ + state->doRotate = ((now.tm_mon != state->lastRotated.tm_mon) || + (now.tm_year != state->lastRotated.tm_year)); ++ if (!state->doRotate) { ++ message(MESS_DEBUG, " log does not need rotating " ++ "(log has been rotated at %d-%d-%d %d:%d, " ++ "that is not month ago yet)\n", state->lastRotated.tm_year, ++ state->lastRotated.tm_mon, state->lastRotated.tm_mday, ++ state->lastRotated.tm_hour, state->lastRotated.tm_min); ++ } + break; + case ROT_YEARLY: + /* rotate if the logs haven't been rotated this year */ + state->doRotate = (now.tm_year != state->lastRotated.tm_year); ++ if (!state->doRotate) { ++ message(MESS_DEBUG, " log does not need rotating " ++ "(log has been rotated at %d-%d-%d %d:%d, " ++ "that is not year ago yet)\n", state->lastRotated.tm_year, ++ state->lastRotated.tm_mon, state->lastRotated.tm_mday, ++ state->lastRotated.tm_hour, state->lastRotated.tm_min); ++ } + break; + default: + /* ack! */ + state->doRotate = 0; + break; + } +- if (log->minsize && sb.st_size < log->minsize) ++ if (log->minsize && sb.st_size < log->minsize) { + state->doRotate = 0; ++ message(MESS_DEBUG, " log does not need rotating " ++ "('misinze' directive is used and the log " ++ "size is smaller than the minsize value"); ++ } + } + + if (log->maxsize && sb.st_size > log->maxsize) +@@ -927,8 +970,6 @@ int findNeedRotating(struct logInfo *log, int logNum, int force) + + if (state->doRotate) { + message(MESS_DEBUG, " log needs rotating\n"); +- } else { +- message(MESS_DEBUG, " log does not need rotating\n"); + } + + return 0; +-- +2.5.5 + + +From 8ed44537bcca96f33d5283a5500faa876d80cd07 Mon Sep 17 00:00:00 2001 +From: jkaluza +Date: Wed, 1 Apr 2015 12:57:54 +0000 +Subject: [PATCH 3/7] Follow-up of previous commit. Also print info when log is + empty. + +Upstream-commit: c0549cfbcc663e540c003f7b2640ee3ebc5960a1 +Signed-off-by: Kamil Dudka +--- + logrotate.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/logrotate.c b/logrotate.c +index 32d26b9..8257ffe 100644 +--- a/logrotate.c ++++ b/logrotate.c +@@ -862,6 +862,9 @@ int findNeedRotating(struct logInfo *log, int logNum, int force) + /* user forced rotation of logs from command line */ + state->doRotate = 1; + } ++ else if (log->maxsize && sb.st_size > log->maxsize) { ++ state->doRotate = 1; ++ } + else if (log->criterium == ROT_SIZE) { + state->doRotate = (sb.st_size >= log->threshhold); + if (!state->doRotate) { +@@ -960,13 +963,17 @@ int findNeedRotating(struct logInfo *log, int logNum, int force) + "size is smaller than the minsize value"); + } + } +- +- if (log->maxsize && sb.st_size > log->maxsize) +- state->doRotate = 1; ++ else if (!state->doRotate) { ++ message(MESS_DEBUG, " log does not need rotating " ++ "(log has been already rotated)"); ++ } + + /* The notifempty flag overrides the normal criteria */ +- if (!(log->flags & LOG_FLAG_IFEMPTY) && !sb.st_size) ++ if (state->doRotate && !(log->flags & LOG_FLAG_IFEMPTY) && !sb.st_size) { + state->doRotate = 0; ++ message(MESS_DEBUG, " log does not need rotating " ++ "(log is empty)"); ++ } + + if (state->doRotate) { + message(MESS_DEBUG, " log needs rotating\n"); +-- +2.5.5 + + +From e92d35acfc02380b70f1bf925a8a0e15cc193d9c Mon Sep 17 00:00:00 2001 +From: jkaluza +Date: Thu, 2 Apr 2015 07:09:43 +0000 +Subject: [PATCH 4/7] Add new -l option to log debug output to file + +Upstream-commit: 2c583abe53972aa6f834b56345b40cb294b0b3a4 +Signed-off-by: Kamil Dudka +--- + log.c | 77 ++++++++++++++++++++----------------------------------------- + log.h | 3 --- + logrotate.c | 12 ++++++++++ + test/test | 37 ++++++++++++++++++++++++++++- + 4 files changed, 73 insertions(+), 56 deletions(-) + +diff --git a/log.c b/log.c +index f0ef130..824aa82 100644 +--- a/log.c ++++ b/log.c +@@ -37,75 +37,48 @@ void logClearFlags(int newFlags) + flags &= ~newFlags; + } + +-#if 0 +-void log(int fd, char *format, ...) ++static void log_once(FILE *where, int level, char *format, va_list args) + { +- int i = 0; +- char *buf = NULL; +- va_list args; +- int size; +- +- va_start(args, format); +- +- do { +- i += 1000; +- if (buf) +- free(buf); +- buf = malloc(i); +- size = vsnprintf(buf, i, format, args); +- } while (size >= i); +- +- write(fd, buf, size); +- +- free(buf); +- +- va_end(args); +-} +-#endif +- +-void message(int level, char *format, ...) +-{ +- va_list args; +- FILE *where = NULL; +- int showTime = 0; +- +- if (errorFile == NULL) +- errorFile = stderr; +- if (messageFile == NULL) +- messageFile = stderr; +- where = errorFile; +- +- if (level >= logLevel) { +- va_start(args, format); ++ int showTime = 0; + + switch (level) { + case MESS_DEBUG: +- where = messageFile; +- showTime = 1; +- break; +- ++ showTime = 1; ++ break; + case MESS_NORMAL: + case MESS_VERBOSE: +- where = messageFile; +- break; +- ++ break; + default: +- if (flags & LOG_TIMES) ++ if (flags & LOG_TIMES) + fprintf(where, "%ld: ", (long) time(NULL)); +- fprintf(errorFile, "error: "); +- break; ++ fprintf(where, "error: "); ++ break; + } + + if (showTime && (flags & LOG_TIMES)) { +- fprintf(where, "%ld:", (long) time(NULL)); ++ fprintf(where, "%ld:", (long) time(NULL)); + } + + vfprintf(where, format, args); + fflush(where); + ++ if (level == MESS_FATAL) ++ exit(1); ++} ++ ++void message(int level, char *format, ...) ++{ ++ va_list args; ++ ++ if (level >= logLevel) { ++ va_start(args, format); ++ log_once(stderr, level, format, args); + va_end(args); ++ } + +- if (level == MESS_FATAL) +- exit(1); ++ if (messageFile != NULL) { ++ va_start(args, format); ++ log_once(messageFile, level, format, args); ++ va_end(args); + } + } +diff --git a/log.h b/log.h +index f3b6da5..49a4ce8 100644 +--- a/log.h ++++ b/log.h +@@ -18,9 +18,6 @@ void message(int level, char *format, ...) + #else + ; + #endif +-#if 0 +-void log(int fd, char *format, ...); +-#endif + void logSetErrorFile(FILE * f); + void logSetMessageFile(FILE * f); + void logSetFlags(int flags); +diff --git a/logrotate.c b/logrotate.c +index 8257ffe..b803685 100644 +--- a/logrotate.c ++++ b/logrotate.c +@@ -2239,6 +2239,8 @@ int main(int argc, const char **argv) + { + int force = 0; + char *stateFile = STATEFILE; ++ char *logFile = NULL; ++ FILE *logFd = 0; + int rc = 0; + int arg; + const char **files; +@@ -2256,6 +2258,7 @@ int main(int argc, const char **argv) + "Path of state file", + "statefile"}, + {"verbose", 'v', 0, 0, 'v', "Display messages during rotation"}, ++ {"log", 'l', POPT_ARG_STRING, &logFile, 'l', "Log file"}, + {"version", '\0', POPT_ARG_NONE, NULL, 'V', "Display version information"}, + POPT_AUTOHELP {0, 0, 0, 0, 0} + }; +@@ -2275,6 +2278,15 @@ int main(int argc, const char **argv) + case 'v': + logSetLevel(MESS_DEBUG); + break; ++ case 'l': ++ logFd = fopen(logFile, "w"); ++ if (!logFd) { ++ message(MESS_ERROR, "error opening log file %s: %s\n", ++ logFile, strerror(errno)); ++ break; ++ } ++ logSetMessageFile(logFd); ++ break; + case 'V': + fprintf(stderr, "logrotate %s\n", VERSION); + poptFreeContext(optCon); +diff --git a/test/test b/test/test +index 3363d42..1584def 100755 +--- a/test/test ++++ b/test/test +@@ -531,7 +531,7 @@ cleanup 17 + # ------------------------------- Test 17 ------------------------------------ + preptest test.log 17 1 0 + # log with 1 byte should not be rotated +-$RLR test-config.17 2>error.log ++$RLR test-config.17 -l logrotate.log 2>error.log + + grep "unexpected } (missing previous '{')" error.log >/dev/null + if [ $? != 0 ]; then +@@ -541,6 +541,14 @@ fi + + rm error.log + ++grep "reading config file test-config.17" logrotate.log >/dev/null ++if [ $? != 0 ]; then ++ echo "There is no log output in logrotate.log" ++ exit 3 ++fi ++ ++rm -f logrotate.log ++ + checkoutput </dev/null + if [ $? != 0 ]; then + echo "test.log must have user:nobody:rwx ACL" ++ getfacl test.log + exit 3 + fi + + getfacl test.log|grep "group::---" >/dev/null + if [ $? != 0 ]; then + echo "test.log must have group::--- ACL" ++ getfacl test.log + exit 3 + fi + + getfacl test.log.1|grep "user:nobody:rwx" >/dev/null + if [ $? != 0 ]; then + echo "test.log.1 must have user:nobody:rwx ACL" ++ getfacl test.log.1 + exit 3 + fi + + getfacl test.log.1|grep "group::---" >/dev/null + if [ $? != 0 ]; then + echo "test.log.1 must have group::--- ACL" ++ getfacl test.log.1 + exit 3 + fi + +@@ -1427,6 +1439,29 @@ fi + + rm -f *test.log* + ++cleanup 60 ++ ++# ------------------------------- Test 60 ------------------------------------ ++# Test we log debug output using -l option when passed. ++preptest test.log 61 1 0 ++ ++$RLR test-config.61 --force -l ./logrotate.log ++ ++DATESTRING=$(/bin/date +%Y-%m-%d-%H) ++ ++grep "reading config file test-config.61" logrotate.log >/dev/null ++if [ $? != 0 ]; then ++ echo "There is no log output in logrotate.log" ++ exit 3 ++fi ++ ++rm -f logrotate.log ++ ++checkoutput < +Date: Wed, 21 Oct 2015 09:23:06 +1300 +Subject: [PATCH 5/7] Support system dates back to the year 1970 + +The system time on Linux can be set back as far as 1970 (the epoch time). +Currently logrotate stops working correctly if the time goes before 1996. +This value (1996) appears to have been hard coded since the code was written +back in 1996. Testing and code analysis shows this can simply be modified +to 1970. + +Upstream-commit: bdbfea38a154b45832daf9c188d1829da2e63996 +Signed-off-by: Kamil Dudka +--- + logrotate.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/logrotate.c b/logrotate.c +index b803685..8fff0eb 100644 +--- a/logrotate.c ++++ b/logrotate.c +@@ -2151,7 +2151,7 @@ static int readState(char *stateFilename) + } + + /* Hack to hide earlier bug */ +- if ((year != 1900) && (year < 1996 || year > 2100)) { ++ if ((year != 1900) && (year < 1970 || year > 2100)) { + message(MESS_ERROR, + "bad year %d for file %s in state file %s\n", year, + argv[0], stateFilename); +-- +2.5.5 + + +From c1ef91cc688c94392f6f82c0348fe51f766c4dbd Mon Sep 17 00:00:00 2001 +From: Rolf Eike Beer +Date: Mon, 4 Jan 2016 10:14:31 +0100 +Subject: [PATCH 6/7] fix Y2k bug in debug messages + +tm_year has the year since 1900, so without this change the message look like +this: + +considering log /var/log/apache2/access_log + log does not need rotating (log has been rotated at 116-0-4 3:10, that is not week ago yet) + +Upstream-commit: b2e01e89f8d677758898ffb93fd9bc31575d965f +Signed-off-by: Kamil Dudka +--- + logrotate.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/logrotate.c b/logrotate.c +index 8fff0eb..66b8ae3 100644 +--- a/logrotate.c ++++ b/logrotate.c +@@ -896,7 +896,7 @@ int findNeedRotating(struct logInfo *log, int logNum, int force) + if (!state->doRotate) { + message(MESS_DEBUG, " log does not need rotating " + "(log has been rotated at %d-%d-%d %d:%d, " +- "that is not week ago yet)\n", state->lastRotated.tm_year, ++ "that is not week ago yet)\n", 1900 + state->lastRotated.tm_year, + state->lastRotated.tm_mon, state->lastRotated.tm_mday, + state->lastRotated.tm_hour, state->lastRotated.tm_min); + } +@@ -909,7 +909,7 @@ int findNeedRotating(struct logInfo *log, int logNum, int force) + if (!state->doRotate) { + message(MESS_DEBUG, " log does not need rotating " + "(log has been rotated at %d-%d-%d %d:%d, " +- "that is not hour ago yet)\n", state->lastRotated.tm_year, ++ "that is not hour ago yet)\n", 1900 + state->lastRotated.tm_year, + state->lastRotated.tm_mon, state->lastRotated.tm_mday, + state->lastRotated.tm_hour, state->lastRotated.tm_min); + } +@@ -922,7 +922,7 @@ int findNeedRotating(struct logInfo *log, int logNum, int force) + if (!state->doRotate) { + message(MESS_DEBUG, " log does not need rotating " + "(log has been rotated at %d-%d-%d %d:%d, " +- "that is not day ago yet)\n", state->lastRotated.tm_year, ++ "that is not day ago yet)\n", 1900 + state->lastRotated.tm_year, + state->lastRotated.tm_mon, state->lastRotated.tm_mday, + state->lastRotated.tm_hour, state->lastRotated.tm_min); + } +@@ -935,7 +935,7 @@ int findNeedRotating(struct logInfo *log, int logNum, int force) + if (!state->doRotate) { + message(MESS_DEBUG, " log does not need rotating " + "(log has been rotated at %d-%d-%d %d:%d, " +- "that is not month ago yet)\n", state->lastRotated.tm_year, ++ "that is not month ago yet)\n", 1900 + state->lastRotated.tm_year, + state->lastRotated.tm_mon, state->lastRotated.tm_mday, + state->lastRotated.tm_hour, state->lastRotated.tm_min); + } +@@ -946,7 +946,7 @@ int findNeedRotating(struct logInfo *log, int logNum, int force) + if (!state->doRotate) { + message(MESS_DEBUG, " log does not need rotating " + "(log has been rotated at %d-%d-%d %d:%d, " +- "that is not year ago yet)\n", state->lastRotated.tm_year, ++ "that is not year ago yet)\n", 1900 + state->lastRotated.tm_year, + state->lastRotated.tm_mon, state->lastRotated.tm_mday, + state->lastRotated.tm_hour, state->lastRotated.tm_min); + } +-- +2.5.5 + + +From 62299605c344ecaf9d7b86e028e7e8ad66786820 Mon Sep 17 00:00:00 2001 +From: Rolf Eike Beer +Date: Mon, 4 Jan 2016 10:18:22 +0100 +Subject: [PATCH 7/7] fix month formatting in debug messages + +The month in struct tm is given in range 0..11, which can lead to messages like +this: + +considering log /var/log/apache2/access_log + log does not need rotating (log has been rotated at 116-0-4 3:10, that is not week ago yet) + +Upstream-commit: 8cbfb079579a1d8b98f1878cec35c269fa1ac5a2 +Signed-off-by: Kamil Dudka +--- + logrotate.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/logrotate.c b/logrotate.c +index 66b8ae3..c695db4 100644 +--- a/logrotate.c ++++ b/logrotate.c +@@ -897,7 +897,7 @@ int findNeedRotating(struct logInfo *log, int logNum, int force) + message(MESS_DEBUG, " log does not need rotating " + "(log has been rotated at %d-%d-%d %d:%d, " + "that is not week ago yet)\n", 1900 + state->lastRotated.tm_year, +- state->lastRotated.tm_mon, state->lastRotated.tm_mday, ++ 1 + state->lastRotated.tm_mon, state->lastRotated.tm_mday, + state->lastRotated.tm_hour, state->lastRotated.tm_min); + } + break; +@@ -910,7 +910,7 @@ int findNeedRotating(struct logInfo *log, int logNum, int force) + message(MESS_DEBUG, " log does not need rotating " + "(log has been rotated at %d-%d-%d %d:%d, " + "that is not hour ago yet)\n", 1900 + state->lastRotated.tm_year, +- state->lastRotated.tm_mon, state->lastRotated.tm_mday, ++ 1 + state->lastRotated.tm_mon, state->lastRotated.tm_mday, + state->lastRotated.tm_hour, state->lastRotated.tm_min); + } + break; +@@ -923,7 +923,7 @@ int findNeedRotating(struct logInfo *log, int logNum, int force) + message(MESS_DEBUG, " log does not need rotating " + "(log has been rotated at %d-%d-%d %d:%d, " + "that is not day ago yet)\n", 1900 + state->lastRotated.tm_year, +- state->lastRotated.tm_mon, state->lastRotated.tm_mday, ++ 1 + state->lastRotated.tm_mon, state->lastRotated.tm_mday, + state->lastRotated.tm_hour, state->lastRotated.tm_min); + } + break; +@@ -936,7 +936,7 @@ int findNeedRotating(struct logInfo *log, int logNum, int force) + message(MESS_DEBUG, " log does not need rotating " + "(log has been rotated at %d-%d-%d %d:%d, " + "that is not month ago yet)\n", 1900 + state->lastRotated.tm_year, +- state->lastRotated.tm_mon, state->lastRotated.tm_mday, ++ 1 + state->lastRotated.tm_mon, state->lastRotated.tm_mday, + state->lastRotated.tm_hour, state->lastRotated.tm_min); + } + break; +@@ -947,7 +947,7 @@ int findNeedRotating(struct logInfo *log, int logNum, int force) + message(MESS_DEBUG, " log does not need rotating " + "(log has been rotated at %d-%d-%d %d:%d, " + "that is not year ago yet)\n", 1900 + state->lastRotated.tm_year, +- state->lastRotated.tm_mon, state->lastRotated.tm_mday, ++ 1 + state->lastRotated.tm_mon, state->lastRotated.tm_mday, + state->lastRotated.tm_hour, state->lastRotated.tm_min); + } + break; +-- +2.5.5 + diff --git a/SOURCES/logrotate-3.8.6-r465.patch b/SOURCES/logrotate-3.8.6-r465.patch index 704dbfa..24f846c 100644 --- a/SOURCES/logrotate-3.8.6-r465.patch +++ b/SOURCES/logrotate-3.8.6-r465.patch @@ -2,7 +2,7 @@ Index: /trunk/logrotate.8 =================================================================== --- a/logrotate.8 (revision 464) +++ b/logrotate.8 (revision 465) -@@ -406,7 +406,8 @@ +@@ -391,7 +391,8 @@ .TP \fBolddir \fIdirectory\fR -Logs are moved into \fIdirectory\fR for rotation. The \fIdirectory\fR diff --git a/SOURCES/logrotate-3.8.6-state-clean.patch b/SOURCES/logrotate-3.8.6-state-clean.patch new file mode 100644 index 0000000..91ba272 --- /dev/null +++ b/SOURCES/logrotate-3.8.6-state-clean.patch @@ -0,0 +1,272 @@ +diff --git a/logrotate.c b/logrotate.c +index 9faf341..06b7100 100644 +--- a/logrotate.c ++++ b/logrotate.c +@@ -62,11 +62,12 @@ extern int asprintf(char **str, const char *fmt, ...); + #endif + + struct logState { +- char *fn; +- struct tm lastRotated; /* only tm_hour, tm_mday, tm_mon, tm_year are good! */ +- struct stat sb; +- int doRotate; +- LIST_ENTRY(logState) list; ++ char *fn; ++ struct tm lastRotated; /* only tm_hour, tm_mday, tm_mon, tm_year are good! */ ++ struct stat sb; ++ int doRotate; ++ int isUsed; /* True if there is real log file in system for this state. */ ++ LIST_ENTRY(logState) list; + }; + + struct logNames { +@@ -204,23 +205,17 @@ static void unescape(char *arg) + } + + #define HASH_SIZE_MIN 64 +-static int allocateHash(void) ++static int allocateHash(unsigned int hs) + { +- struct logInfo *log; +- unsigned int hs; + int i; + +- hs = 0; +- +- for (log = logs.tqh_first; log != NULL; log = log->list.tqe_next) +- hs += log->numFiles; +- +- hs *= 2; +- + /* Enforce some reasonable minimum hash size */ + if (hs < HASH_SIZE_MIN) + hs = HASH_SIZE_MIN; + ++ message(MESS_DEBUG, "Allocating hash table for state file, size %lu B\n", ++ hs * (sizeof(struct logStates *) + sizeof(struct logState) ) ); ++ + states = calloc(hs, sizeof(struct logStates *)); + if (states == NULL) { + message(MESS_ERROR, "could not allocate memory for " +@@ -271,6 +266,7 @@ static struct logState *newState(const char *fn) + } + + new->doRotate = 0; ++ new->isUsed = 0; + + memset(&new->lastRotated, 0, sizeof(new->lastRotated)); + new->lastRotated.tm_hour = now.tm_hour; +@@ -850,9 +846,10 @@ int findNeedRotating(struct logInfo *log, int logNum, int force) + return 1; + } + +- state = findState(log->files[logNum]); +- state->doRotate = 0; +- state->sb = sb; ++ state = findState(log->files[logNum]); ++ state->doRotate = 0; ++ state->sb = sb; ++ state->isUsed = 1; + + if ((sb.st_mode & S_IFMT) == S_IFLNK) { + message(MESS_DEBUG, " log %s is symbolic link. Rotation of symbolic" +@@ -1820,6 +1817,8 @@ static int writeState(char *stateFilename) + int fdsave; + struct stat sb; + char *tmpFilename = NULL; ++ struct tm now = *localtime(&nowSecs); ++ time_t now_time, last_time; + + tmpFilename = malloc(strlen(stateFilename) + 5 ); + if (tmpFilename == NULL) { +@@ -1924,9 +1923,22 @@ static int writeState(char *stateFilename) + if (bytes < 0) + error = bytes; + ++#define SECONDS_IN_YEAR 31556926 ++ + for (i = 0; i < hashSize && error == 0; i++) { + for (p = states[i]->head.lh_first; p != NULL && error == 0; + p = p->list.le_next) { ++ ++ /* Skip states which are not used for more than a year. */ ++ now_time = mktime(&now); ++ last_time = mktime(&p->lastRotated); ++ if (!p->isUsed && difftime(now_time, last_time) > SECONDS_IN_YEAR) { ++ message(MESS_DEBUG, "Removing %s from state file, " ++ "because it does not exist and has not been rotated for one year\n", ++ p->fn); ++ continue; ++ } ++ + error = fputc('"', f) == EOF; + for (chptr = p->fn; *chptr && error == 0; chptr++) { + switch (*chptr) { +@@ -2010,23 +2022,27 @@ static int readState(char *stateFilename) + + error = stat(stateFilename, &f_stat); + +- if ((error && errno == ENOENT) || (!error && f_stat.st_size == 0)) { +- /* create the file before continuing to ensure we have write +- access to the file */ +- f = fopen(stateFilename, "w"); +- if (!f) { +- message(MESS_ERROR, "error creating state file %s: %s\n", +- stateFilename, strerror(errno)); +- return 1; ++ if ((error && errno == ENOENT) || (!error && f_stat.st_size == 0)) { ++ /* create the file before continuing to ensure we have write ++ access to the file */ ++ f = fopen(stateFilename, "w"); ++ if (!f) { ++ message(MESS_ERROR, "error creating state file %s: %s\n", ++ stateFilename, strerror(errno)); ++ return 1; ++ } ++ fprintf(f, "logrotate state -- version 2\n"); ++ fclose(f); ++ ++ if (allocateHash(64) != 0) ++ return 1; ++ ++ return 0; ++ } else if (error) { ++ message(MESS_ERROR, "error stat()ing state file %s: %s\n", ++ stateFilename, strerror(errno)); ++ return 1; + } +- fprintf(f, "logrotate state -- version 2\n"); +- fclose(f); +- return 0; +- } else if (error) { +- message(MESS_ERROR, "error stat()ing state file %s: %s\n", +- stateFilename, strerror(errno)); +- return 1; +- } + + f = fopen(stateFilename, "r"); + if (!f) { +@@ -2050,6 +2066,13 @@ static int readState(char *stateFilename) + return 1; + } + ++ /* Try to estimate how many state entries we have in the state file. ++ * We expect single entry to have around 80 characters (Of course this is ++ * just an estimation). During the testing I've found out that 200 entries ++ * per single hash entry gives good mem/performance ratio. */ ++ if (allocateHash(f_stat.st_size / 80 / 200) != 0) ++ return 1; ++ + line++; + + while (fgets(buf, sizeof(buf) - 1, f)) { +@@ -2244,9 +2267,6 @@ int main(int argc, const char **argv) + poptFreeContext(optCon); + nowSecs = time(NULL); + +- if (allocateHash() != 0) +- return 1; +- + if (readState(stateFile)) + exit(1); + +diff --git a/test/test b/test/test +index f7f3cf4..4048197 100755 +--- a/test/test ++++ b/test/test +@@ -1460,4 +1460,61 @@ EOF + checkmail test.log-$DATESTRING zero + + ++cleanup 67 ++ ++# ------------------------------- Test 67 ------------------------------------ ++# firstaction and lastaction scripts should be called if no file is rotated ++preptest test.log 67 1 0 ++ ++DATESTRING=$(/bin/date +%Y%m%d) ++TODAY=$(/bin/date "+%Y-%m-%d" 2>/dev/null) ++ ++echo removed > "test.log$TODAY" ++ ++$RLR test-config.67 --force ++ ++cat scriptout|grep firstaction >/dev/null ++if [ $? != 0 ]; then ++ echo "scriptout should contain 'firstaction'" ++ exit 3 ++fi ++ ++cat scriptout|grep lastaction >/dev/null ++if [ $? != 0 ]; then ++ echo "scriptout should contain 'lastaction'" ++ exit 3 ++fi ++ ++cleanup 68 ++ ++# ------------------------------- Test 68 ------------------------------------ ++# Old state file entries should be removed when not used. Logrotate should ++# not freeze on big state file. ++preptest test.log 68 1 0 ++ ++cat > state << EOF ++logrotate state -- version 1 ++"$PWD/test.log" 2000-1-1 ++EOF ++ ++for i in {1..200000} ++do ++ echo "\"$PWD/removed.log$i\" 2000-1-1" >> state ++done ++ ++ ++$RLR test-config.68 --force ++ ++cat state|grep test.log >/dev/null ++if [ $? != 0 ]; then ++ echo "state file should contain 'test.log'" ++ exit 3 ++fi ++ ++cat state|grep removed.log >/dev/null ++if [ $? == 0 ]; then ++ echo "state file should not contain 'removed.log'" ++ exit 3 ++fi ++ + cleanup +diff --git a/test/test-config.67.in b/test/test-config.67.in +new file mode 100644 +index 0000000..69b9fff +--- /dev/null ++++ b/test/test-config.67.in +@@ -0,0 +1,16 @@ ++create ++ ++&DIR&/test.log { ++ daily ++ dateext ++ dateformat %Y-%m-%d ++ rotate 1 ++ ++ firstaction ++ echo "firstaction" > scriptout ++ endscript ++ ++ lastaction ++ echo "lastaction" >> scriptout ++ endscript ++} +diff --git a/test/test-config.68.in b/test/test-config.68.in +new file mode 100644 +index 0000000..e8e1c79 +--- /dev/null ++++ b/test/test-config.68.in +@@ -0,0 +1,6 @@ ++create ++ ++&DIR&/test.log { ++ daily ++ rotate 1 ++} diff --git a/SOURCES/logrotate-3.8.6-statusfile.patch b/SOURCES/logrotate-3.8.6-statusfile.patch new file mode 100644 index 0000000..1610173 --- /dev/null +++ b/SOURCES/logrotate-3.8.6-statusfile.patch @@ -0,0 +1,12 @@ +diff --git a/examples/logrotate.cron b/examples/logrotate.cron +index c6d50d4..967932e 100644 +--- a/examples/logrotate.cron ++++ b/examples/logrotate.cron +@@ -1,6 +1,6 @@ + #!/bin/sh + +-/usr/sbin/logrotate /etc/logrotate.conf ++/usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf + EXITVALUE=$? + if [ $EXITVALUE != 0 ]; then + /usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]" diff --git a/SOURCES/rwtab b/SOURCES/rwtab new file mode 100644 index 0000000..3210e47 --- /dev/null +++ b/SOURCES/rwtab @@ -0,0 +1 @@ +dirs /var/lib/logrotate diff --git a/SPECS/logrotate.spec b/SPECS/logrotate.spec index 244299a..15d0e93 100644 --- a/SPECS/logrotate.spec +++ b/SPECS/logrotate.spec @@ -1,17 +1,23 @@ Summary: Rotates, compresses, removes and mails system log files Name: logrotate Version: 3.8.6 -Release: 7%{?dist} +Release: 12%{?dist} License: GPL+ Group: System Environment/Base Url: https://fedorahosted.org/logrotate/ Source: https://fedorahosted.org/releases/l/o/logrotate/logrotate-%{version}.tar.gz +Source1: rwtab Patch0: logrotate-3.8.6-force.patch Patch1: logrotate-3.8.6-r465.patch Patch2: logrotate-3.8.6-sortglob.patch Patch3: logrotate-3.8.6-r460.patch Patch4: logrotate-3.8.6-compress-subject.patch Patch5: logrotate-3.8.6-olddircopy.patch +Patch6: logrotate-3.8.6-state-clean.patch +Patch7: logrotate-3.8.6-statusfile.patch + +# fix #1192936 - provide diagnostic in case log does not need rotating +Patch9: logrotate-3.8.6-diagnostic.patch Requires: coreutils >= 5.92 popt BuildRequires: libselinux-devel popt-devel libacl-devel acl @@ -37,6 +43,9 @@ log files on your system. %patch3 -p1 -b .r460 %patch4 -p1 -b .compressmail %patch5 -p1 -b .olddircopy +%patch6 -p1 -b .stateclean +%patch7 -p1 -b .statusfile +%patch9 -p1 %build make %{?_smp_mflags} RPM_OPT_FLAGS="$RPM_OPT_FLAGS" WITH_SELINUX=yes WITH_ACL=yes @@ -49,11 +58,25 @@ rm -rf $RPM_BUILD_ROOT make PREFIX=$RPM_BUILD_ROOT MANDIR=%{_mandir} install mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/logrotate.d mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/cron.daily -mkdir -p $RPM_BUILD_ROOT/%{_localstatedir}/lib +mkdir -p $RPM_BUILD_ROOT/%{_localstatedir}/lib/logrotate install -p -m 644 examples/logrotate-default $RPM_BUILD_ROOT/%{_sysconfdir}/logrotate.conf install -p -m 755 examples/logrotate.cron $RPM_BUILD_ROOT/%{_sysconfdir}/cron.daily/logrotate -touch $RPM_BUILD_ROOT/%{_localstatedir}/lib/logrotate.status +touch $RPM_BUILD_ROOT/%{_localstatedir}/lib/logrotate/logrotate.status + +# Make sure logrotate is able to run on read-only root +mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/rwtab.d +install -m644 %{SOURCE1} $RPM_BUILD_ROOT%{_sysconfdir}/rwtab.d/logrotate + +%pre +# If /var/lib/logrotate/logrotate.status does not exist, create it and copy +# the /var/lib/logrotate.status in it (if it exists). We have to do that in pre +# script, otherwise the /var/lib/logrotate/logrotate.status would not be there, +# because during the update, it is removed/renamed. +if [ ! -d %{_localstatedir}/lib/logrotate/ -a -f %{_localstatedir}/lib/logrotate.status ]; then + mkdir -p %{_localstatedir}/lib/logrotate + cp -a %{_localstatedir}/lib/logrotate.status %{_localstatedir}/lib/logrotate +fi %clean rm -rf $RPM_BUILD_ROOT @@ -67,9 +90,29 @@ rm -rf $RPM_BUILD_ROOT %attr(0700, root, root) %config(noreplace) %{_sysconfdir}/cron.daily/logrotate %attr(0644, root, root) %config(noreplace) %{_sysconfdir}/logrotate.conf %attr(0755, root, root) %dir %{_sysconfdir}/logrotate.d -%attr(0644, root, root) %verify(not size md5 mtime) %config(noreplace) %{_localstatedir}/lib/logrotate.status +%attr(0755, root, root) %dir %{_localstatedir}/lib/logrotate +%attr(0644, root, root) %verify(not size md5 mtime) %config(noreplace) %{_localstatedir}/lib/logrotate/logrotate.status +%config(noreplace) %{_sysconfdir}/rwtab.d/logrotate %changelog +* Thu Jul 14 2016 Kamil Dudka - 3.8.6-12 +- make the /var/lib/logrotate directory owned by logrotate (#1272236) + +* Mon Jul 11 2016 Kamil Dudka - 3.8.6-11 +- fix #1354203 - remove the fix for bug #1321980 + +* Fri Jul 01 2016 Kamil Dudka - 3.8.6-10 +- fix #1192936 - provide diagnostic in case log does not need rotating +- fix #1321980 - do not exit if status file is corrupted + +* Fri Jul 01 2016 Jan Kaluza - 3.8.6-9 +- fix #1272236 - add missing rwtab file + +* Fri Mar 11 2016 Jan Kaluza - 3.8.6-8 +- fix #1201252 - delete unused entries in state file, fix bad performance + with big state file +- fix #1272236 - move logrotate.status to /var/lib/logrotate and add it to rwtab.d + * Mon Nov 09 2015 Jan Kaluza - 3.8.6-7 - fix #1163437 - support olddir on different device with copy or copytruncate