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 +}