svn commit: r250478 - stable/9/usr.sbin/newsyslog

Mark Johnston markj at FreeBSD.org
Fri May 10 20:55:40 UTC 2013


Author: markj
Date: Fri May 10 20:55:39 2013
New Revision: 250478
URL: http://svnweb.freebsd.org/changeset/base/250478

Log:
  MFC r248776:
    Fix interval-based rotations when the -t flag is used. In this case, find
    the most-recently archived logfile and use its mtime to determine whether
    or not to rotate, as in the non-timestamped case.
  
    Previously we would just try to use the mtime of <logfile>.0, which always
    results in a rotation since it generally doesn't exist in the -t case.
  
  Approved by:	emaste

Modified:
  stable/9/usr.sbin/newsyslog/newsyslog.c
Directory Properties:
  stable/9/usr.sbin/newsyslog/   (props changed)

Modified: stable/9/usr.sbin/newsyslog/newsyslog.c
==============================================================================
--- stable/9/usr.sbin/newsyslog/newsyslog.c	Fri May 10 20:02:15 2013	(r250477)
+++ stable/9/usr.sbin/newsyslog/newsyslog.c	Fri May 10 20:55:39 2013	(r250478)
@@ -274,7 +274,7 @@ static void parse_args(int argc, char **
 static int parse_doption(const char *doption);
 static void usage(void);
 static int log_trim(const char *logname, const struct conf_entry *log_ent);
-static int age_old_log(char *file);
+static int age_old_log(const char *file);
 static void savelog(char *from, char *to);
 static void createdir(const struct conf_entry *ent, char *dirpart);
 static void createlog(const struct conf_entry *ent);
@@ -1445,6 +1445,66 @@ oldlog_entry_compare(const void *a, cons
 }
 
 /*
+ * Check whether the file corresponding to dp is an archive of the logfile
+ * logfname, based on the timefnamefmt format string. Return true and fill out
+ * tm if this is the case; otherwise return false.
+ */
+static int
+validate_old_timelog(const struct dirent *dp, const char *logfname, struct tm *tm)
+{
+	size_t logfname_len;
+	char *s;
+	int c;
+
+	logfname_len = strlen(logfname);
+
+	if (dp->d_type != DT_REG)
+		return (0);
+	/* Ignore everything but files with our logfile prefix. */
+	if (strncmp(dp->d_name, logfname, logfname_len) != 0)
+		return (0);
+	/* Ignore the actual non-rotated logfile. */
+	if (dp->d_namlen == logfname_len)
+		return (0);
+
+	/*
+	 * Make sure we created have found a logfile, so the
+	 * postfix is valid, IE format is: '.<time>(.[bgx]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]);
+		return (0);
+	}
+	if ((s = strptime(&dp->d_name[logfname_len + 1],
+	    timefnamefmt, tm)) == NULL) {
+		/*
+		 * We could special case "old" sequentially named logfiles here,
+		 * but we do not as that would require special handling to
+		 * decide which one was the oldest compared to "new" time based
+		 * logfiles.
+		 */
+		if (verbose)
+			printf("Ignoring %s which does not "
+			    "match time format\n", dp->d_name);
+		return (0);
+	}
+
+	for (c = 0; c < COMPRESS_TYPES; c++)
+		if (strcmp(s, compress_type[c].suffix) == 0)
+			/* We're done. */
+			return (1);
+
+	if (verbose)
+		printf("Ignoring %s which has unexpected extension '%s'\n",
+		    dp->d_name, s);
+
+	return (0);
+}
+
+/*
  * Delete the oldest logfiles, when using time based filenames.
  */
 static void
@@ -1453,12 +1513,10 @@ delete_oldest_timelog(const struct conf_
 	char *logfname, *s, *dir, errbuf[80];
 	int dirfd, i, logcnt, max_logcnt, valid;
 	struct oldlog_entry *oldlogs;
-	size_t logfname_len;
 	struct dirent *dp;
 	const char *cdir;
 	struct tm tm;
 	DIR *dirp;
-	int c;
 
 	oldlogs = malloc(MAX_OLDLOGS * sizeof(struct oldlog_entry));
 	max_logcnt = MAX_OLDLOGS;
@@ -1476,7 +1534,6 @@ delete_oldest_timelog(const struct conf_
 		err(1, "basename()");
 	if ((logfname = strdup(s)) == NULL)
 		err(1, "strdup()");
-	logfname_len = strlen(logfname);
 	if (strcmp(logfname, "/") == 0)
 		errx(1, "Invalid log filename - became '/'");
 
@@ -1488,50 +1545,8 @@ delete_oldest_timelog(const struct conf_
 		err(1, "Cannot open log directory '%s'", dir);
 	dirfd = dirfd(dirp);
 	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 created 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) {
-			/*
-			 * We could special case "old" sequentially
-			 * named logfiles here, but we do not as that
-			 * would require special handling to decide
-			 * which one was the oldest compared to "new"
-			 * time based logfiles.
-			 */
-			if (verbose)
-				printf("Ignoring %s which does not "
-				    "match time format\n", dp->d_name);
-			continue;
-		}
-
-		for (c = 0; c < COMPRESS_TYPES; c++)
-			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);
+		if (validate_old_timelog(dp, logfname, &tm) == 0)
 			continue;
-		}
 
 		/*
 		 * We should now have old an old rotated logfile, so
@@ -2258,13 +2273,66 @@ sizefile(const char *file)
 	return (kbytes(dbtob(sb.st_blocks)));
 }
 
-/* Return the age of old log file (file.0) */
+/*
+ * Return the mtime of the most recent archive of the logfile, using timestamp
+ * based filenames.
+ */
+static time_t
+mtime_old_timelog(const char *file)
+{
+	struct stat sb;
+	struct tm tm;
+	int dir_fd;
+	time_t t;
+	struct dirent *dp;
+	DIR *dirp;
+	char *s, *logfname, *dir;
+
+	t = -1;
+
+	if ((dir = dirname(file)) == NULL) {
+		warn("dirname() of '%s'", file);
+		return (t);
+	}
+	if ((s = basename(file)) == NULL) {
+		warn("basename() of '%s'", file);
+		return (t);
+	} else if (s[0] == '/') {
+		warnx("Invalid log filename '%s'", s);
+		return (t);
+	} else if ((logfname = strdup(s)) == NULL)
+		err(1, "strdup()");
+
+	if ((dirp = opendir(dir)) == NULL) {
+		warn("Cannot open log directory '%s'", dir);
+		return (t);
+	}
+	dir_fd = dirfd(dirp);
+	/* Open the archive dir and find the most recent archive of logfname. */
+	while ((dp = readdir(dirp)) != NULL) {
+		if (validate_old_timelog(dp, logfname, &tm) == 0)
+			continue;
+
+		if (fstatat(dir_fd, logfname, &sb, 0) == -1) {
+			warn("Cannot stat '%s'", file);
+			continue;
+		}
+		if (t < sb.st_mtime)
+			t = sb.st_mtime;
+	}
+	closedir(dirp);
+
+	return (t);
+}
+
+/* Return the age in hours of the most recent archive of the logfile. */
 static int
-age_old_log(char *file)
+age_old_log(const char *file)
 {
 	struct stat sb;
 	const char *logfile_suffix;
 	char tmp[MAXPATHLEN + sizeof(".0") + COMPRESS_SUFFIX_MAXLEN + 1];
+	time_t mtime;
 
 	if (archtodir) {
 		char *p;
@@ -2293,14 +2361,22 @@ age_old_log(char *file)
 		(void) strlcpy(tmp, file, sizeof(tmp));
 	}
 
-	strlcat(tmp, ".0", sizeof(tmp));
-	logfile_suffix = get_logfile_suffix(tmp);
-	if (logfile_suffix == NULL)
-		return (-1);
-	(void) strlcat(tmp, logfile_suffix, sizeof(tmp));
-	if (stat(tmp, &sb) < 0)
-		return (-1);
-	return ((int)(ptimeget_secs(timenow) - sb.st_mtime + 1800) / 3600);
+	if (timefnamefmt != NULL) {
+		mtime = mtime_old_timelog(tmp);
+		if (mtime == -1)
+			return (-1);
+	} else {
+		strlcat(tmp, ".0", sizeof(tmp));
+		logfile_suffix = get_logfile_suffix(tmp);
+		if (logfile_suffix == NULL)
+			return (-1);
+		(void) strlcat(tmp, logfile_suffix, sizeof(tmp));
+		if (stat(tmp, &sb) < 0)
+			return (-1);
+		mtime = sb.st_mtime;
+	}
+
+	return ((int)(ptimeget_secs(timenow) - mtime + 1800) / 3600);
 }
 
 /* Skip Over Blanks */


More information about the svn-src-stable-9 mailing list