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 <jkaluza@ec1272ba-9ed1-42ef-8245-99669996828e>
+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 <kdudka@redhat.com>
+---
+ 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 <<EOF
++test.log 0
++test.log.$DATESTRING 0 zero
++EOF
++
+ cleanup
+diff --git a/test/test-config.61.in b/test/test-config.61.in
+new file mode 100644
+index 0000000..423241f
+--- /dev/null
++++ b/test/test-config.61.in
+@@ -0,0 +1,8 @@
++create
++
++&DIR&/test.log {
++    daily
++    dateext
++    dateformat .%Y-%m-%d-%H
++    rotate 1
++}
+-- 
+2.5.5
+
+
+From ba81f77a3af97456dc6a33fd4470a7e713020026 Mon Sep 17 00:00:00 2001
+From: jkaluza <jkaluza@ec1272ba-9ed1-42ef-8245-99669996828e>
+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 <kdudka@redhat.com>
+---
+ 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 <jkaluza@ec1272ba-9ed1-42ef-8245-99669996828e>
+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 <kdudka@redhat.com>
+---
+ 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 <jkaluza@ec1272ba-9ed1-42ef-8245-99669996828e>
+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 <kdudka@redhat.com>
+---
+ 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 <<EOF
+ test.log 0 zero
+ EOF
+@@ -801,24 +809,28 @@ $RLR test-config.32 --force
+ getfacl test.log|grep "user:nobody:rwx" >/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 <<EOF
++test.log 0
++test.log.$DATESTRING 0 zero
++EOF
++
+ cleanup 64
+ 
+ # ------------------------------- Test 64 ------------------------------------
+-- 
+2.5.5
+
+
+From 895de6554c4f7005ca3da8877490ee7f3d4f2918 Mon Sep 17 00:00:00 2001
+From: Matt Bennett <matt.bennett@alliedtelesis.co.nz>
+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 <kdudka@redhat.com>
+---
+ 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 <eike@sf-mail.de>
+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 <kdudka@redhat.com>
+---
+ 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 <eike@sf-mail.de>
+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 <kdudka@redhat.com>
+---
+ 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 <kdudka@redhat.com> - 3.8.6-12
+- make the /var/lib/logrotate directory owned by logrotate (#1272236)
+
+* Mon Jul 11 2016 Kamil Dudka <kdudka@redhat.com> - 3.8.6-11
+- fix #1354203 - remove the fix for bug #1321980
+
+* Fri Jul 01 2016 Kamil Dudka <kdudka@redhat.com> - 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 <jkaluza@redhat.com> - 3.8.6-9
+- fix #1272236 - add missing rwtab file
+
+* Fri Mar 11 2016 Jan Kaluza <jkaluza@redhat.com> - 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 <jkaluza@redhat.com> - 3.8.6-7
 - fix #1163437 - support olddir on different device with copy or copytruncate