diff --git a/SOURCES/logrotate-3.8.6-compress-subject.patch b/SOURCES/logrotate-3.8.6-compress-subject.patch
new file mode 100644
index 0000000..9ccb0dc
--- /dev/null
+++ b/SOURCES/logrotate-3.8.6-compress-subject.patch
@@ -0,0 +1,139 @@
+diff --git a/logrotate.c b/logrotate.c
+index 4ef044e..9faf341 100644
+--- a/logrotate.c
++++ b/logrotate.c
+@@ -662,22 +662,20 @@ static int mailLog(struct logInfo *log, char *logFile, char *mailCommand,
+ static int mailLogWrapper(char *mailFilename, char *mailCommand,
+ 			  int logNum, struct logInfo *log)
+ {
+-    /* if the log is compressed (and we're not mailing a
+-     * file whose compression has been delayed), we need
+-     * to uncompress it */
+-    if ((log->flags & LOG_FLAG_COMPRESS) &&
+-	!((log->flags & LOG_FLAG_DELAYCOMPRESS) &&
+-	  (log->flags & LOG_FLAG_MAILFIRST))) {
+-	if (mailLog(log, mailFilename, mailCommand,
+-		    log->uncompress_prog, log->logAddress,
+-		    log->files[logNum]))
+-	    return 1;
+-    } else {
+-	if (mailLog(log, mailFilename, mailCommand, NULL,
+-		    log->logAddress, mailFilename))
+-	    return 1;
+-    }
+-    return 0;
++	/* if the log is compressed (and we're not mailing a
++	* file whose compression has been delayed), we need
++	* to uncompress it */
++	if ((log->flags & LOG_FLAG_COMPRESS) && !(log->flags & LOG_FLAG_DELAYCOMPRESS)) {
++		if (mailLog(log, mailFilename, mailCommand,
++			log->uncompress_prog, log->logAddress,
++			(log->flags & LOG_FLAG_MAILFIRST) ? log->files[logNum] : mailFilename))
++			return 1;
++	} else {
++		if (mailLog(log, mailFilename, mailCommand, NULL,
++			log->logAddress, mailFilename))
++			return 1;
++	}
++	return 0;
+ }
+ 
+ static int copyTruncate(char *currLog, char *saveLog, struct stat *sb,
+diff --git a/test/test b/test/test
+index e9ce46f..f7f3cf4 100755
+--- a/test/test
++++ b/test/test
+@@ -132,6 +132,9 @@ createlogs() {
+ 
+ checkmail() {
+     (echo -s $PWD/$1 user@myhost.org; echo $2) | diff -u - mail-out
++    if [ $? != 0 ]; then
++        exit 5
++    fi
+ }
+ 
+ checkoutput() {
+@@ -429,7 +432,7 @@ test.log 0
+ scriptout 0 foo
+ EOF
+ 
+-checkmail test.log first
++checkmail test.log.2.gz first
+ 
+ # check rotation into a directory given as a relative pathname
+ cleanup 12
+@@ -1424,4 +1427,37 @@ fi
+ 
+ rm -f *test.log*
+ 
++cleanup 64
++
++# ------------------------------- Test 64 ------------------------------------
++# filename in mail's subject with compress directive and maillast directive
++# should be the name of the removed log
++preptest test.log 64 1 0
++
++DATESTRING=$(/bin/date +%Y%m%d)
++
++$RLR test-config.64 --force
++checkoutput <<EOF
++test.log 0
++EOF
++
++checkmail test.log-$DATESTRING.gz zero
++
++cleanup 65
++
++# ------------------------------- Test 65 ------------------------------------
++# filename in mail's subject without compress directive and maillast directive
++# should be the name of the removed log
++preptest test.log 65 1 0
++
++DATESTRING=$(/bin/date +%Y%m%d)
++
++$RLR test-config.65 --force
++checkoutput <<EOF
++test.log 0
++EOF
++
++checkmail test.log-$DATESTRING zero
++
++
+ cleanup
+diff --git a/test/test-config.64.in b/test/test-config.64.in
+new file mode 100644
+index 0000000..c817734
+--- /dev/null
++++ b/test/test-config.64.in
+@@ -0,0 +1,13 @@
++create
++
++&DIR&/test.log {
++    daily
++    dateext
++    dateformat -%Y%m%d
++    rotate 0
++    compress
++    nosharedscripts
++    dateext
++    mail user@myhost.org
++    maillast
++}
+diff --git a/test/test-config.65.in b/test/test-config.65.in
+new file mode 100644
+index 0000000..19007f5
+--- /dev/null
++++ b/test/test-config.65.in
+@@ -0,0 +1,12 @@
++create
++
++&DIR&/test.log {
++    daily
++    dateext
++    dateformat -%Y%m%d
++    rotate 0
++    nosharedscripts
++    dateext
++    mail user@myhost.org
++    maillast
++}
diff --git a/SOURCES/logrotate-3.8.6-r460.patch b/SOURCES/logrotate-3.8.6-r460.patch
new file mode 100644
index 0000000..6805e7f
--- /dev/null
+++ b/SOURCES/logrotate-3.8.6-r460.patch
@@ -0,0 +1,733 @@
+diff --git a/config.c b/config.c
+index e6b6a53..e9992e3 100644
+--- a/config.c
++++ b/config.c
+@@ -220,6 +220,61 @@ static char *readPath(const char *configFile, int lineNum, char *key,
+ 	return NULL;
+ }
+ 
++static int readModeUidGid(const char *configFile, int lineNum, char *key,
++							const char *directive, mode_t *mode, uid_t *uid,
++							gid_t *gid) {
++	char u[200], g[200];
++	int m;
++	char tmp;
++	int rc;
++	struct group *group;
++	struct passwd *pw = NULL;
++
++	rc = sscanf(key, "%o %199s %199s%c", &m, u, g, &tmp);
++	/* We support 'key <owner> <group> notation now */
++	if (rc == 0) {
++		rc = sscanf(key, "%199s %199s%c", u, g, &tmp);
++		/* Simulate that we have read mode and keep the default value. */
++		if (rc > 0) {
++			m = *mode;
++			rc += 1;
++		}
++	}
++
++	if (rc == 4) {
++		message(MESS_ERROR, "%s:%d extra arguments for "
++			"%s\n", configFile, lineNum, directive);
++		return -1;
++	}
++
++	if (rc > 0) {
++		*mode = m;
++	}
++
++	if (rc > 1) {
++		pw = getpwnam(u);
++		if (!pw) {
++			message(MESS_ERROR, "%s:%d unknown user '%s'\n",
++				configFile, lineNum, u);
++			return -1;
++		}
++		*uid = pw->pw_uid;
++		endpwent();
++	}
++	if (rc > 2) {
++		group = getgrnam(g);
++		if (!group) {
++			message(MESS_ERROR, "%s:%d unknown group '%s'\n",
++				configFile, lineNum, g);
++			return -1;
++		}
++		*gid = group->gr_gid;
++		endgrent();
++	}
++
++	return 0;
++}
++
+ static char *readAddress(const char *configFile, int lineNum, char *key,
+ 			 char **startPtr, char **buf, size_t length)
+ {
+@@ -249,6 +304,55 @@ static char *readAddress(const char *configFile, int lineNum, char *key,
+ 	return NULL;
+ }
+ 
++static int do_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid) {
++	struct stat sb;
++
++	if (stat(path, &sb) != 0) {
++		if (mkdir(path, mode) != 0 && errno != EEXIST) {
++			message(MESS_ERROR, "error creating %s: %s\n",
++				path, strerror(errno));
++			return -1;
++		}
++		if ((uid != sb.st_uid || gid != sb.st_gid) && 
++			chown(path, uid, gid)) {
++			message(MESS_ERROR, "error setting owner of %s to uid %d and gid %d: %s\n",
++				path, uid, gid, strerror(errno));
++			return -1;
++		}
++    }
++	else if (!S_ISDIR(sb.st_mode)) {
++		message(MESS_ERROR, "path %s already exists, but it is not a directory\n",
++			path);
++		errno = ENOTDIR;
++		return -1;
++	}
++
++	return 0;
++}
++
++static int mkpath(const char *path, mode_t mode, uid_t uid, gid_t gid) {
++	char *pp;
++	char *sp;
++	int rv;
++	char *copypath = strdup(path);
++
++	rv = 0;
++	pp = copypath;
++	while (rv == 0 && (sp = strchr(pp, '/')) != 0) {
++		if (sp != pp) {
++			*sp = '\0';
++			rv = do_mkdir(copypath, mode, uid, gid);
++			*sp = '/';
++		}
++		pp = sp + 1;
++	}
++	if (rv == 0) {
++		rv = do_mkdir(path, mode, uid, gid);
++	}
++	free(copypath);
++	return rv;
++}
++
+ static int checkFile(const char *fname)
+ {
+ 	int i;
+@@ -330,6 +434,9 @@ static void copyLogInfo(struct logInfo *to, struct logInfo *from)
+     to->createGid = from->createGid;
+     to->suUid = from->suUid;
+     to->suGid = from->suGid;
++    to->olddirMode = from->olddirMode;
++    to->olddirUid = from->olddirUid;
++    to->olddirGid = from->olddirGid;
+     if (from->compress_options_count) {
+         poptDupArgv(from->compress_options_count, from->compress_options_list, 
+                     &to->compress_options_count,  &to->compress_options_list);
+@@ -539,6 +646,11 @@ int readAllConfigPaths(const char **paths)
+ 		.createMode = NO_MODE,
+ 		.createUid = NO_UID,
+ 		.createGid = NO_GID,
++		.olddirMode = NO_MODE,
++		.olddirUid = NO_UID,
++		.olddirGid = NO_GID,
++		.suUid = NO_UID,
++		.suGid = NO_GID,
+ 		.compress_options_list = NULL,
+ 		.compress_options_count = 0
+     };
+@@ -579,13 +691,19 @@ static int globerr(const char *pathname, int theerr)
+ 		free(newlog->what); \
+ 		newlog->what = NULL; \
+ 	} while (0);
++#define RAISE_ERROR() \
++	if (newlog != defConfig) { \
++		state = STATE_ERROR; \
++		continue; \
++	} else { \
++		goto error; \
++	}
+ #define MAX_NESTING 16U
+ 
+ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
+ {
+     int fd;
+     char *buf, *endtag, *key = NULL;
+-    char foo;
+     off_t length;
+     int lineNum = 1;
+     unsigned long long multiplier;
+@@ -595,11 +713,8 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
+     struct logInfo *newlog = defConfig;
+     char *start, *chptr;
+     char *dirName;
+-    struct group *group;
+     struct passwd *pw = NULL;
+     int rc;
+-    char createOwner[200], createGroup[200];
+-    int createMode;
+     struct stat sb, sb2;
+     glob_t globResult;
+     const char **argv;
+@@ -611,6 +726,7 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
+ 	static unsigned recursion_depth = 0U;
+ 	char *globerr_msg = NULL;
+ 	int in_config = 0;
++	int rv;
+ 	struct flock fd_lock = {
+ 		.l_start = 0,
+ 		.l_len = 0,
+@@ -807,53 +923,22 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
+ 				} else if (!strcmp(key, "maillast")) {
+ 					newlog->flags &= ~LOG_FLAG_MAILFIRST;
+ 				} else if (!strcmp(key, "su")) {
++					mode_t tmp_mode = NO_MODE;
+ 					free(key);
+ 					key = isolateLine(&start, &buf, length);
+ 					if (key == NULL)
+ 						continue;
+ 
+-					rc = sscanf(key, "%199s %199s%c", createOwner,
+-								createGroup, &foo);
+-					if (rc == 3) {
+-						message(MESS_ERROR, "%s:%d extra arguments for "
+-							"su\n", configFile, lineNum);
+-						if (newlog != defConfig) {
+-							state = STATE_ERROR;
+-							continue;
+-						} else {
+-							goto error;
+-						}
++					rv = readModeUidGid(configFile, lineNum, key, "su", 
++								   &tmp_mode, &newlog->suUid,
++								   &newlog->suGid);
++					if (rv == -1) {
++						RAISE_ERROR();
+ 					}
+-
+-					if (rc > 0) {
+-						pw = getpwnam(createOwner);
+-						if (!pw) {
+-							message(MESS_ERROR, "%s:%d unknown user '%s'\n",
+-								configFile, lineNum, createOwner);
+-							if (newlog != defConfig) {
+-								state = STATE_ERROR;
+-								continue;
+-							} else {
+-								goto error;
+-							}
+-						}
+-						newlog->suUid = pw->pw_uid;
+-						endpwent();
+-					}
+-					if (rc > 1) {
+-						group = getgrnam(createGroup);
+-						if (!group) {
+-							message(MESS_ERROR, "%s:%d unknown group '%s'\n",
+-								configFile, lineNum, createGroup);
+-							if (newlog != defConfig) {
+-								state = STATE_ERROR;
+-								continue;
+-							} else {
+-								goto error;
+-							}
+-						}
+-						newlog->suGid = group->gr_gid;
+-						endgrent();
++					else if (tmp_mode != NO_MODE) {
++						message(MESS_ERROR, "%s:%d extra arguments for "
++								"su\n", configFile, lineNum);
++						RAISE_ERROR();
+ 					}
+ 
+ 					newlog->flags |= LOG_FLAG_SU;
+@@ -863,65 +948,30 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
+ 					if (key == NULL)
+ 						continue;
+ 
+-					rc = sscanf(key, "%o %199s %199s%c", &createMode,
+-							createOwner, createGroup, &foo);
+-					/* We support 'create <owner> <group> notation now */
+-					if (rc == 0) {
+-						rc = sscanf(key, "%199s %199s%c",
+-								createOwner, createGroup, &foo);
+-						/* Simulate that we have read createMode and se it
+-						 * to NO_MODE. */
+-						if (rc > 0) {
+-							createMode = NO_MODE;
+-							rc += 1;
+-						}
+-					}
+-					if (rc == 4) {
+-						message(MESS_ERROR, "%s:%d extra arguments for "
+-							"create\n", configFile, lineNum);
+-						if (newlog != defConfig) {
+-							state = STATE_ERROR;
+-							continue;
+-						} else {
+-							goto error;
+-						}
++					rv = readModeUidGid(configFile, lineNum, key, "create",
++								   &newlog->createMode, &newlog->createUid,
++								   &newlog->createGid);
++					if (rv == -1) {
++						RAISE_ERROR();
+ 					}
+ 
+-					if (rc > 0)
+-						newlog->createMode = createMode;
+-
+-					if (rc > 1) {
+-						pw = getpwnam(createOwner);
+-						if (!pw) {
+-							message(MESS_ERROR, "%s:%d unknown user '%s'\n",
+-								configFile, lineNum, createOwner);
+-							if (newlog != defConfig) {
+-								state = STATE_ERROR;
+-								continue;
+-							} else {
+-								goto error;
+-							}
+-						}
+-						newlog->createUid = pw->pw_uid;
+-						endpwent();
+-					}
+-					if (rc > 2) {
+-						group = getgrnam(createGroup);
+-						if (!group) {
+-							message(MESS_ERROR, "%s:%d unknown group '%s'\n",
+-								configFile, lineNum, createGroup);
+-							if (newlog != defConfig) {
+-								state = STATE_ERROR;
+-								continue;
+-							} else {
+-								goto error;
+-							}
+-						}
+-						newlog->createGid = group->gr_gid;
+-						endgrent();
++					newlog->flags |= LOG_FLAG_CREATE;
++				} else if (!strcmp(key, "createolddir")) {
++					free(key);
++					key = isolateLine(&start, &buf, length);
++					if (key == NULL)
++						continue;
++
++					rv = readModeUidGid(configFile, lineNum, key, "createolddir",
++								   &newlog->olddirMode, &newlog->olddirUid,
++								   &newlog->olddirGid);
++					if (rv == -1) {
++						RAISE_ERROR();
+ 					}
+ 
+-					newlog->flags |= LOG_FLAG_CREATE;
++					newlog->flags |= LOG_FLAG_OLDDIRCREATE;
++				} else if (!strcmp(key, "nocreateolddir")) {
++					newlog->flags &= ~LOG_FLAG_OLDDIRCREATE;
+ 				} else if (!strcmp(key, "nocreate")) {
+ 					newlog->flags &= ~LOG_FLAG_CREATE;
+ 				} else if (!strcmp(key, "size") || !strcmp(key, "minsize") ||
+@@ -945,12 +995,7 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
+ 							free(opt);
+ 							message(MESS_ERROR, "%s:%d unknown unit '%c'\n",
+ 								configFile, lineNum, key[l]);
+-							if (newlog != defConfig) {
+-								state = STATE_ERROR;
+-								continue;
+-							} else {
+-								goto error;
+-							}
++							RAISE_ERROR();
+ 						} else {
+ 							multiplier = 1;
+ 						}
+@@ -960,12 +1005,7 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
+ 							message(MESS_ERROR, "%s:%d bad size '%s'\n",
+ 								configFile, lineNum, key);
+ 							free(opt);
+-							if (newlog != defConfig) {
+-								state = STATE_ERROR;
+-								continue;
+-							} else {
+-								goto error;
+-							}
++							RAISE_ERROR();
+ 						}
+ 						if (!strncmp(opt, "size", 4)) {
+ 						  newlog->criterium = ROT_SIZE;
+@@ -1015,12 +1055,7 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
+ 							message(MESS_ERROR,
+ 								"%s:%d bad rotation count '%s'\n",
+ 								configFile, lineNum, key);
+-							if (newlog != defConfig) {
+-								state = STATE_ERROR;
+-								continue;
+-							} else {
+-								goto error;
+-							}
++							RAISE_ERROR();
+ 						}
+ 					}
+ 					else continue;
+@@ -1034,12 +1069,7 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
+ 						if (*chptr || newlog->logStart < 0) {
+ 							message(MESS_ERROR, "%s:%d bad start count '%s'\n",
+ 								configFile, lineNum, key);
+-							if (newlog != defConfig) {
+-								state = STATE_ERROR;
+-								continue;
+-							} else {
+-								goto error;
+-							}
++							RAISE_ERROR();
+ 						}
+ 					}
+ 					else continue;
+@@ -1052,12 +1082,7 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
+ 						if (*chptr || newlog->rotateAge < 0) {
+ 							message(MESS_ERROR, "%s:%d bad maximum age '%s'\n",
+ 								configFile, lineNum, start);
+-							if (newlog != defConfig) {
+-								state = STATE_ERROR;
+-								continue;
+-							} else {
+-								goto error;
+-							}
++							RAISE_ERROR();
+ 						}
+ 					}
+ 					else continue;
+@@ -1069,12 +1094,7 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
+ 					freeLogItem(logAddress);
+ 					if (!(newlog->logAddress = readAddress(configFile, lineNum,
+ 										"mail", &start, &buf, length))) {
+-						if (newlog != defConfig) {
+-						state = STATE_ERROR;
+-						continue;
+-						} else {
+-						goto error;
+-						}
++						RAISE_ERROR();
+ 					}
+ 					else continue;
+ 				} else if (!strcmp(key, "nomail")) {
+@@ -1177,31 +1197,8 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
+ 
+ 					if (!(newlog->oldDir = readPath(configFile, lineNum,
+ 									"olddir", &start, &buf, length))) {
+-						if (newlog != defConfig) {
+-							state = STATE_ERROR;
+-							continue;
+-						} else {
+-							goto error;
+-						}
+-					}
+-
+-#if 0
+-					if (stat(newlog->oldDir, &sb)) {
+-						message(MESS_ERROR, "%s:%d error verifying olddir "
+-							"path %s: %s\n", configFile, lineNum,
+-							newlog->oldDir, strerror(errno));
+-						free(newlog->oldDir);
+-						goto error;
++						RAISE_ERROR();
+ 					}
+-
+-					if (!S_ISDIR(sb.st_mode)) {
+-						message(MESS_ERROR, "%s:%d olddir path %s is not a "
+-							"directory\n", configFile, lineNum,
+-							newlog->oldDir);
+-						free(newlog->oldDir);
+-						goto error;
+-					}
+-#endif
+ 					message(MESS_DEBUG, "olddir is now %s\n", newlog->oldDir);
+ 				} else if (!strcmp(key, "extension")) {
+ 					if ((key = isolateValue
+@@ -1222,24 +1219,14 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
+ 					if (!
+ 						(newlog->compress_prog =
+ 							readPath(configFile, lineNum, "compress", &start, &buf, length))) {
+-						if (newlog != defConfig) {
+-							state = STATE_ERROR;
+-							continue;
+-						} else {
+-							goto error;
+-						}
++						RAISE_ERROR();
+ 					}
+ 
+ 					if (access(newlog->compress_prog, X_OK)) {
+ 						message(MESS_ERROR,
+ 							"%s:%d compression program %s is not an executable file\n",
+ 							configFile, lineNum, newlog->compress_prog);
+-						if (newlog != defConfig) {
+-							state = STATE_ERROR;
+-							continue;
+-						} else {
+-							goto error;
+-						}
++						RAISE_ERROR();
+ 					}
+ 
+ 					message(MESS_DEBUG, "compress_prog is now %s\n",
+@@ -1252,24 +1239,14 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
+ 						(newlog->uncompress_prog =
+ 							readPath(configFile, lineNum, "uncompress",
+ 								&start, &buf, length))) {
+-						if (newlog != defConfig) {
+-							state = STATE_ERROR;
+-							continue;
+-						} else {
+-							goto error;
+-						}
++						RAISE_ERROR();
+ 					}
+ 
+ 					if (access(newlog->uncompress_prog, X_OK)) {
+ 						message(MESS_ERROR,
+ 							"%s:%d uncompression program %s is not an executable file\n",
+ 							configFile, lineNum, newlog->uncompress_prog);
+-						if (newlog != defConfig) {
+-							state = STATE_ERROR;
+-							continue;
+-						} else {
+-							goto error;
+-						}
++						RAISE_ERROR();
+ 					}
+ 
+ 					message(MESS_DEBUG, "uncompress_prog is now %s\n",
+@@ -1285,12 +1262,7 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
+ 					}
+ 
+ 					if (!(options = isolateLine(&start, &buf, length))) {
+-						if (newlog != defConfig) {
+-							state = STATE_ERROR;
+-							continue;
+-						} else {
+-							goto error;
+-						}
++						RAISE_ERROR();
+ 					}
+ 
+ 					if (poptParseArgvString(options,
+@@ -1300,12 +1272,7 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
+ 							"%s:%d invalid compression options\n",
+ 							configFile, lineNum);
+ 						free(options);
+-						if (newlog != defConfig) {
+-							state = STATE_ERROR;
+-							continue;
+-						} else {
+-							goto error;
+-						}
++						RAISE_ERROR();
+ 					}
+ 
+ 					message(MESS_DEBUG, "compress_options is now %s\n",
+@@ -1318,12 +1285,7 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
+ 						(newlog->compress_ext =
+ 							readPath(configFile, lineNum, "compress-ext",
+ 								&start, &buf, length))) {
+-						if (newlog != defConfig) {
+-							state = STATE_ERROR;
+-							continue;
+-						} else {
+-							goto error;
+-						}
++						RAISE_ERROR();
+ 					}
+ 
+ 					message(MESS_DEBUG, "compress_ext is now %s\n",
+@@ -1484,45 +1446,57 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
+ 				globerr_msg = NULL;
+ 				if (!(newlog->flags & LOG_FLAG_MISSINGOK))
+ 					goto error;
+-				}
++			}
+ 
+-				if (newlog->oldDir) {
++			if (newlog->oldDir) {
+ 				for (i = 0; i < newlog->numFiles; i++) {
+ 					char *ld;
++					int rv;
+ 					dirName = ourDirName(newlog->files[i]);
+ 					if (stat(dirName, &sb2)) {
+-					message(MESS_ERROR,
+-						"%s:%d error verifying log file "
+-						"path %s: %s\n", configFile, lineNum,
+-						dirName, strerror(errno));
+-					free(dirName);
+-					goto error;
++						message(MESS_ERROR,
++							"%s:%d error verifying log file "
++							"path %s: %s\n", configFile, lineNum,
++							dirName, strerror(errno));
++						free(dirName);
++						goto error;
+ 					}
+-					ld = alloca(strlen(dirName) + strlen(newlog->oldDir) +
+-						2);
++					ld = alloca(strlen(dirName) + strlen(newlog->oldDir) + 2);
+ 					sprintf(ld, "%s/%s", dirName, newlog->oldDir);
+ 					free(dirName);
+ 
+-					if (newlog->oldDir[0] != '/')
+-					dirName = ld;
+-					else
+-					dirName = newlog->oldDir;
+-					if (stat(dirName, &sb)) {
+-					message(MESS_ERROR, "%s:%d error verifying olddir "
+-						"path %s: %s\n", configFile, lineNum,
+-						dirName, strerror(errno));
+-					goto error;
++					if (newlog->oldDir[0] != '/') {
++						dirName = ld;
++					}
++					else {
++						dirName = newlog->oldDir;
++					}
++
++					rv = stat(dirName, &sb);
++					if (rv) {
++						if (errno == ENOENT && newlog->flags & LOG_FLAG_OLDDIRCREATE) {
++							if (mkpath(dirName, newlog->olddirMode,
++								newlog->olddirUid, newlog->olddirGid)) {
++								goto error;
++							}
++						}
++						else {
++							message(MESS_ERROR, "%s:%d error verifying olddir "
++								"path %s: %s\n", configFile, lineNum,
++								dirName, strerror(errno));
++							goto error;
++						}
+ 					}
+ 
+ 					if (sb.st_dev != sb2.st_dev) {
+-					message(MESS_ERROR,
+-						"%s:%d olddir %s and log file %s "
+-						"are on different devices\n", configFile,
+-						lineNum, newlog->oldDir, newlog->files[i]);
+-					goto error;
++						message(MESS_ERROR,
++							"%s:%d olddir %s and log file %s "
++							"are on different devices\n", configFile,
++							lineNum, newlog->oldDir, newlog->files[i]);
++						goto error;
+ 					}
+ 				}
+-				}
++			}
+ 
+ 				newlog = defConfig;
+ 				state = STATE_DEFINITION_END;
+diff --git a/logrotate.8 b/logrotate.8
+index 8cb9c2f..2cd2370 100644
+--- a/logrotate.8
++++ b/logrotate.8
+@@ -216,6 +216,16 @@ file for the omitted attributes. This option can be disabled using the
+ \fBnocreate\fR option.
+ 
+ .TP
++\fBcreateolddir \fImode\fR \fIowner\fR \fIgroup\fR
++If the directory specified by \fBolddir\fR directive does not exist, it is
++created. \fImode\fR specifies the mode for the \fBolddir\fR directory
++in octal (the same as \fBchmod\fR(2)), \fIowner\fR specifies the user name
++who will own the \fBolddir\fR directory, and \fIgroup\fR specifies the group
++the \fBolddir\fR directory will belong to. This option can be disabled using the
++\fBnocreateolddir\fR option.
++
++
++.TP
+ \fBdaily\fR
+ Log files are rotated every day.
+ 
+@@ -350,6 +360,10 @@ Do not truncate the original log file in place after creating a copy
+ New log files are not created (this overrides the \fBcreate\fR option).
+ 
+ .TP
++\fBnocreateolddir\fR
++\fBolddir\fR directory is not created by logrotate when it does not exist.
++
++.TP
+ \fBnodelaycompress\fR
+ Do not postpone compression of the previous log file to the next rotation cycle
+ (this overrides the \fBdelaycompress\fR option).
+diff --git a/logrotate.h b/logrotate.h
+index 813418e..cf42703 100644
+--- a/logrotate.h
++++ b/logrotate.h
+@@ -20,6 +20,7 @@
+ #define LOG_FLAG_SHRED		(1 << 10)
+ #define LOG_FLAG_SU			(1 << 11)
+ #define LOG_FLAG_DATEYESTERDAY	(1 << 12)
++#define LOG_FLAG_OLDDIRCREATE	(1 << 13)
+ 
+ #define NO_MODE ((mode_t) -1)
+ #define NO_UID  ((uid_t) -1)
+@@ -55,6 +56,9 @@ struct logInfo {
+     gid_t createGid;
+     uid_t suUid;			/* switch user to this uid and group to this gid */
+     gid_t suGid;
++    mode_t olddirMode;
++    uid_t olddirUid;
++    uid_t olddirGid;
+     /* these are at the end so they end up nil */
+     const char **compress_options_list;
+     int compress_options_count;
+diff --git a/test/test b/test/test
+index 25b76a6..e9ce46f 100755
+--- a/test/test
++++ b/test/test
+@@ -453,9 +453,15 @@ cleanup 13
+ # ------------------------------- Test 13 ------------------------------------
+ preptest test.log 13 1 0
+ rm -rf testdir
+-mkdir testdir
+ $RLR test-config.13 --force
+ 
++ls -l|grep testdir|grep "drwx------." 2>/dev/null >/dev/null
++if [ $? != 0 ]; then
++	echo "testdir should have mode 2700, but it has:"
++	ls -l|grep testdir
++	exit 3
++fi
++
+ checkoutput <<EOF
+ test.log 0
+ testdir/test.log.1 0 zero
+@@ -888,13 +894,15 @@ $RLR test-config.35 --force
+ 
+ getfacl test.log|grep "user:nobody:rwx" >/dev/null
+ if [ $? != 0 ]; then
+-	echo "test.log must not contain user:nobody:rwx"
++	echo "test.log must contain user:nobody:rwx"
++	getfacl test.log
+ 	exit 3
+ fi
+ 
+ getfacl test.log.1|grep "user:nobody:rwx" >/dev/null
+ if [ $? != 0 ]; then
+ 	echo "test.log.1 must contain user:nobody:rwx"
++	getfacl test.log.1
+ 	exit 3
+ fi
+ 
+diff --git a/test/test-config.13.in b/test/test-config.13.in
+index 31a29ef..dc2efd5 100644
+--- a/test/test-config.13.in
++++ b/test/test-config.13.in
+@@ -4,4 +4,5 @@ create
+     monthly
+     rotate 1
+     olddir &DIR&/testdir
++    createolddir 700 &USER& &GROUP&
+ }
diff --git a/SOURCES/logrotate-3.8.6-r465.patch b/SOURCES/logrotate-3.8.6-r465.patch
new file mode 100644
index 0000000..704dbfa
--- /dev/null
+++ b/SOURCES/logrotate-3.8.6-r465.patch
@@ -0,0 +1,16 @@
+Index: /trunk/logrotate.8
+===================================================================
+--- a/logrotate.8	(revision 464)
++++ b/logrotate.8	(revision 465)
+@@ -406,7 +406,8 @@
+ .TP
+ \fBolddir \fIdirectory\fR
+-Logs are moved into \fIdirectory\fR for rotation. The \fIdirectory\fR
+-must be on the same physical device as the log file being rotated,
+-and is assumed to be relative to the directory holding the log file
++Logs are moved into \fIdirectory\fR for rotation. The \fIdirectory\fR must be
++on the same physical device as the log file being rotated, unless \fBcopy\fR,
++\fBcopytruncate\fR or \fBrenamecopy\fR option is used. The \fIdirectory\fR
++is assumed to be relative to the directory holding the log file
+ unless an absolute path name is specified. When this option is used all
+ old versions of the log end up in \fIdirectory\fR.  This option may be
diff --git a/SOURCES/logrotate-3.8.6-sortglob.patch b/SOURCES/logrotate-3.8.6-sortglob.patch
new file mode 100644
index 0000000..6537631
--- /dev/null
+++ b/SOURCES/logrotate-3.8.6-sortglob.patch
@@ -0,0 +1,209 @@
+diff --git a/logrotate.c b/logrotate.c
+index 174a26b..4ef044e 100644
+--- a/logrotate.c
++++ b/logrotate.c
+@@ -77,6 +77,11 @@ struct logNames {
+     char *baseName;
+ };
+ 
++struct compData {
++	int prefix_len;
++	const char *dformat;
++};
++
+ struct logStates {
+ 	LIST_HEAD(stateSet, logState) head;
+ } **states;
+@@ -142,6 +147,34 @@ int switch_user_permanently(const struct logInfo *log) {
+ 	return 0;
+ }
+ 
++static int compGlobResult(const void *result1, const void *result2, void *data)  {
++	struct tm time;
++	time_t t1, t2;
++	struct compData *d = (struct compData *) data;
++	const char *r1 = *(const char **)(result1);
++	const char *r2 = *(const char **)(result2);
++
++	memset(&time, 0, sizeof(struct tm));
++	strptime(r1 + d->prefix_len, d->dformat, &time);
++	t1 = mktime(&time);
++
++	memset(&time, 0, sizeof(struct tm));
++	strptime(r2 + d->prefix_len, d->dformat, &time);
++	t2 = mktime(&time);
++
++	if (t1 < t2) return -1;
++	if (t1 > t2) return  1;
++	return 0;
++}
++
++static void sortGlobResult(glob_t *result, int prefix_len, const char *dformat) {
++	struct compData d;
++	if (!dformat || *dformat == '\0') return;
++	d.prefix_len = prefix_len;
++	d.dformat = dformat;
++	qsort_r(result->gl_pathv, result->gl_pathc, sizeof(char *), compGlobResult, &d);
++}
++
+ static void unescape(char *arg)
+ {
+ 	char *p = arg;
+@@ -923,7 +956,7 @@ int prerotateSingleLog(struct logInfo *log, int logNum, struct logState *state,
+ #define DATEEXT_LEN 64
+ #define PATTERN_LEN (DATEEXT_LEN * 2)
+ 	char dext_str[DATEEXT_LEN];
+-	char dformat[DATEEXT_LEN];
++	char dformat[DATEEXT_LEN] = "";
+ 	char dext_pattern[PATTERN_LEN];
+ 	char *dext;
+ 
+@@ -1112,6 +1145,7 @@ int prerotateSingleLog(struct logInfo *log, int logNum, struct logState *state,
+ 		}
+ 	    rc = glob(glob_pattern, 0, globerr, &globResult);
+ 	    if (!rc && globResult.gl_pathc > 0) {
++		sortGlobResult(&globResult, strlen(rotNames->dirName) + 1 + strlen(rotNames->baseName), dformat);
+ 		for (i = 0; i < globResult.gl_pathc && !hasErrors; i++) {
+ 		    struct stat sbprev;
+ 
+@@ -1176,6 +1210,7 @@ int prerotateSingleLog(struct logInfo *log, int logNum, struct logState *state,
+ 	    /* remove the first (n - rotateCount) matches
+ 	     * no real rotation needed, since the files have
+ 	     * the date in their name */
++		sortGlobResult(&globResult, strlen(rotNames->dirName) + 1 + strlen(rotNames->baseName), dformat);
+ 	    for (i = 0; i < globResult.gl_pathc; i++) {
+ 		if (!stat((globResult.gl_pathv)[i], &fst_buf)) {
+ 		    if ((i <= ((int) globResult.gl_pathc - rotateCount))
+diff --git a/test/test b/test/test
+index 793bf77..25b76a6 100755
+--- a/test/test
++++ b/test/test
+@@ -1347,4 +1347,73 @@ test.log 0
+ test.log.1 0 zero
+ EOF
+ 
++cleanup 54
++
++# ------------------------------- Test 54 ------------------------------------
++# removing last log file when using %Y-%m-%d
++rm -f *test.log*
++preptest test.log 54 1 0
++
++DATE=""
++for i in {1..60}
++do
++    DATE=$(/bin/date "+%Y-%m-%d" --date "$i day ago" 2>/dev/null)   
++    echo "x" > test.log-$DATE
++done
++
++$RLR test-config.54 --force
++
++if [ -e test.log-$DATE ]; then
++    echo "File test.log-$DATE should not exist (it should be deleted)"
++    exit 3
++fi
++
++rm -f *test.log*
++
++cleanup 55
++
++# ------------------------------- Test 55 ------------------------------------
++# removing last log file when using %s and hourly
++rm -f *test.log*
++preptest test.log 55 1 0
++
++DATE=""
++for i in {1..60}
++do
++    DATE=$(/bin/date "+%s" --date "$i hour ago" 2>/dev/null)   
++    echo "x" > test.log-$DATE.gz
++done
++
++$RLR test-config.55 --force
++
++if [ -e test.log-$DATE.gz ]; then
++    echo "File test.log-$DATE.gz should not exist (it should be deleted)"
++    exit 3
++fi
++
++rm -f *test.log*
++
++cleanup 56
++
++# ------------------------------- Test 56 ------------------------------------
++# removing last log file when using %d-%m-%Y
++rm -f *test.log*
++preptest test.log 56 1 0
++
++DATE=""
++for i in {1..60}
++do
++    DATE=$(/bin/date "+%d-%m-%Y" --date "$i day ago" 2>/dev/null)   
++    echo "x" > test.log-$DATE
++done
++
++$RLR test-config.56 --force
++
++if [ -e test.log-$DATE ]; then
++    echo "File test.log-$DATE should not exist (it should be deleted)"
++    exit 3
++fi
++
++rm -f *test.log*
++
+ cleanup
+diff --git a/test/test-config.54.in b/test/test-config.54.in
+new file mode 100644
+index 0000000..c946af1
+--- /dev/null
++++ b/test/test-config.54.in
+@@ -0,0 +1,8 @@
++create
++
++&DIR&/test.log {
++    daily
++	dateext
++	dateformat -%Y-%m-%d
++    rotate 60
++}
+diff --git a/test/test-config.55.in b/test/test-config.55.in
+new file mode 100644
+index 0000000..8b10ad1
+--- /dev/null
++++ b/test/test-config.55.in
+@@ -0,0 +1,21 @@
++create
++
++# continue and throw no error message when log file is not present
++missingok
++
++# truncate the original log file in place after creating a copy
++copytruncate
++
++# compress the file
++compress
++
++# do only rotate when not empty
++notifempty
++
++&DIR&/test.log {
++    hourly
++	dateext
++	dateformat -%s
++    rotate 60
++    nosharedscripts
++}
+diff --git a/test/test-config.56.in b/test/test-config.56.in
+new file mode 100644
+index 0000000..adaf2a5
+--- /dev/null
++++ b/test/test-config.56.in
+@@ -0,0 +1,8 @@
++create
++
++&DIR&/test.log {
++    daily
++	dateext
++	dateformat -%d-%m-%Y
++    rotate 60
++}
diff --git a/SPECS/logrotate.spec b/SPECS/logrotate.spec
index e90b4e3..715294f 100644
--- a/SPECS/logrotate.spec
+++ b/SPECS/logrotate.spec
@@ -1,12 +1,16 @@
 Summary: Rotates, compresses, removes and mails system log files
 Name: logrotate
 Version: 3.8.6
-Release: 4%{?dist}
+Release: 6%{?dist}
 License: GPL+
 Group: System Environment/Base
 Url: https://fedorahosted.org/logrotate/
 Source: https://fedorahosted.org/releases/l/o/logrotate/logrotate-%{version}.tar.gz
 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
 
 Requires: coreutils >= 5.92 popt
 BuildRequires: libselinux-devel popt-devel libacl-devel acl
@@ -27,6 +31,10 @@ log files on your system.
 %setup -q
 
 %patch0 -p1 -b .force
+%patch1 -p1 -b .r465
+%patch2 -p1 -b .sortglob
+%patch3 -p1 -b .r460
+%patch4 -p1 -b .compressmail
 
 %build
 make %{?_smp_mflags} RPM_OPT_FLAGS="$RPM_OPT_FLAGS" WITH_SELINUX=yes WITH_ACL=yes
@@ -54,12 +62,21 @@ rm -rf $RPM_BUILD_ROOT
 %attr(0755, root, root) %{_sbindir}/logrotate
 %attr(0644, root, root) %{_mandir}/man8/logrotate.8*
 %attr(0644, root, root) %{_mandir}/man5/logrotate.conf.5*
-%attr(0700, root, root) %{_sysconfdir}/cron.daily/logrotate
+%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
 
 %changelog
+* Tue Oct 06 2015 Jan Kaluza <jkaluza@redhat.com> - 3.8.6-6
+- fix #1244156 - make filename in subject consistent when used with compress
+
+* Thu Apr 23 2015 Jan Kaluza <jkaluza@redhat.com> - 3.8.6-5
+- mention copy/copytruncate/renamecopy influence to olddir option (#1175292)
+- delete last log when dateformat cannot be sorted alphabetically (#1174208)
+- mark cron.daily/logrotate as config file (#1174207)
+- create olddir diectory if it does not exist (#1187161)
+
 * Fri Jan 24 2014 Daniel Mach <dmach@redhat.com> - 3.8.6-4
 - Mass rebuild 2014-01-24