bin/166448: [patch] newsyslog -t fails to find previous rotated log

Eugene Grosbein eugen at grosbein.pp.ru
Tue Mar 27 18:10:12 UTC 2012


>Number:         166448
>Category:       bin
>Synopsis:       [patch] newsyslog -t fails to find previous rotated log
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Mar 27 18:10:11 UTC 2012
>Closed-Date:
>Last-Modified:
>Originator:     Eugene Grosbein
>Release:        FreeBSD 8.3-PRERELEASE amd64
>Organization:
RDTC JSC
>Environment:
System: FreeBSD grosbein.pp.ru 8.3-PRERELEASE FreeBSD 8.3-PRERELEASE #19: Tue Mar 20 03:24:04 NOVT 2012 root at grosbein.pp.ru:/usr/local/obj/usr/local/src/sys/DADV amd64

>Description:

	newsyslog.conf(5) has "when" field instructing newsyslog to find
	previous rotated copy of log and look if it is older than "when" hours.

	newsyslog always looks for "file.0" and this is wrong when -t flag is used.

>How-To-Repeat:

	Use newsyslog -t and non-zero value in "when" field:

/var/log/cron 600 3 * 8 at T C

	This should rotate log three times a day starting from midnight.

>Fix:

--- usr.sbin/newsyslog/newsyslog.c.orig	2012-03-27 22:43:06.000000000 +0700
+++ usr.sbin/newsyslog/newsyslog.c	2012-03-28 00:53:21.000000000 +0700
@@ -2206,6 +2206,77 @@
 	return (kbytes(dbtob(sb.st_blocks)));
 }
 
+/* Return the age of previous old log file, when using time based filenames. */
+static time_t
+find_oldest_timelog(const char *dir, const char *logfname)
+{
+	struct stat sb;
+	int c, valid;
+	size_t logfname_len;
+	struct tm tm;
+	time_t oldt;
+	struct dirent *dp;
+	DIR *dirp;
+	char *s;
+
+	if ((dirp = opendir(dir)) == NULL)
+		err(1, "Cannot open log directory '%s'", dir);
+
+	oldt = -1;
+	logfname_len = strlen(logfname);
+	while ((dp = readdir(dirp)) != NULL) {
+		if (dp->d_type != DT_REG)
+			continue;
+		/* Ignore everything but files with our logfile prefix */
+		if (strncmp(dp->d_name, logfname, logfname_len) != 0)
+			continue;
+		/* Ignore the actual non-rotated logfile */
+		if (dp->d_namlen == logfname_len)
+			continue;
+		/*
+		 * Make sure we have found a logfile, so the
+		 * postfix is valid, IE format is: '.<time>(.[bg]z)?'.
+		 */
+		if (dp->d_name[logfname_len] != '.') {
+			if (verbose)
+				printf("Ignoring %s which has unexpected "
+				    "extension '%s'\n", dp->d_name,
+				    &dp->d_name[logfname_len]);
+			continue;
+		}
+		if ((s = strptime(&dp->d_name[logfname_len + 1],
+			    timefnamefmt, &tm)) == NULL) {
+			if (verbose)
+				printf("Ignoring %s which does not "
+				    "match time format\n", dp->d_name);
+			continue;
+		}
+
+		valid = 0;
+		c = 0;
+		while (!valid && c < COMPRESS_TYPES)
+			if (strcmp(s, compress_type[c++].suffix) == 0)
+				valid = 1;
+
+		if (valid != 1) {
+			if (verbose)
+				printf("Ignoring %s which has unexpected "
+				    "extension '%s'\n", dp->d_name, s);
+			continue;
+		}
+		if (stat(dp->d_name, &sb) < 0)
+			err(1, "Cannot stat '%s'", dp->d_name);
+
+		/* We have found more recent old logfile */
+		if (oldt < sb.st_mtime)
+			oldt = sb.st_mtime;
+	}
+	closedir(dirp);
+
+	/* Return -1 if nothing found */
+	return oldt;
+}
+
 /* Return the age of old log file (file.0) */
 static int
 age_old_log(char *file)
@@ -2241,6 +2312,17 @@
 		(void) strlcpy(tmp, file, sizeof(tmp));
 	}
 
+	if (timefnamefmt != NULL) {
+                char *bd;
+                time_t t;
+
+	        if ((bd = dirname(tmp)) == NULL)
+                        err(1, "'%s'", tmp);
+                if ((t = find_oldest_timelog(bd, basename(tmp))) == -1)
+                        return (-1);
+                return ((int)(ptimeget_secs(timenow) - t + 1800) / 3600);
+	}
+
 	strlcat(tmp, ".0", sizeof(tmp));
 	logfile_suffix = get_logfile_suffix(tmp);
 	if (logfile_suffix == NULL)


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list