Date: Fri, 10 May 2013 20:56:07 +0000 (UTC) From: Mark Johnston <markj@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org Subject: svn commit: r250479 - stable/8/usr.sbin/newsyslog Message-ID: <201305102056.r4AKu7h7047000@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: markj Date: Fri May 10 20:56:07 2013 New Revision: 250479 URL: http://svnweb.freebsd.org/changeset/base/250479 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/8/usr.sbin/newsyslog/newsyslog.c Directory Properties: stable/8/usr.sbin/newsyslog/ (props changed) Modified: stable/8/usr.sbin/newsyslog/newsyslog.c ============================================================================== --- stable/8/usr.sbin/newsyslog/newsyslog.c Fri May 10 20:55:39 2013 (r250478) +++ stable/8/usr.sbin/newsyslog/newsyslog.c Fri May 10 20:56:07 2013 (r250479) @@ -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); @@ -1442,6 +1442,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 @@ -1450,7 +1510,6 @@ 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; @@ -1472,7 +1531,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 '/'"); @@ -1484,50 +1542,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]); + if (validate_old_timelog(dp, logfname, &tm) == 0) 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 (int 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); - continue; - } /* * We should now have old an old rotated logfile, so @@ -2223,13 +2239,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; @@ -2258,14 +2327,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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201305102056.r4AKu7h7047000>