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. PR: bin/166448 Approved by: emaste (co-mentor) Tested by: Marco Steinbach <coco executive-computing.de> MFC after: 2 weeks
This commit is contained in:
parent
1da66a2776
commit
91ba008fc5
@ -276,7 +276,7 @@ static void parse_args(int argc, char **argv);
|
||||
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);
|
||||
@ -1446,6 +1446,66 @@ oldlog_entry_compare(const void *a, const void *b)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
@ -1453,14 +1513,12 @@ static void
|
||||
delete_oldest_timelog(const struct conf_entry *ent, const char *archive_dir)
|
||||
{
|
||||
char *logfname, *s, *dir, errbuf[80];
|
||||
int dir_fd, i, logcnt, max_logcnt, valid;
|
||||
int dir_fd, i, logcnt, max_logcnt;
|
||||
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;
|
||||
@ -1478,7 +1536,6 @@ delete_oldest_timelog(const struct conf_entry *ent, const char *archive_dir)
|
||||
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 '/'");
|
||||
|
||||
@ -1490,51 +1547,9 @@ delete_oldest_timelog(const struct conf_entry *ent, const char *archive_dir)
|
||||
err(1, "Cannot open log directory '%s'", dir);
|
||||
dir_fd = dirfd(dirp);
|
||||
while ((dp = readdir(dirp)) != NULL) {
|
||||
if (dp->d_type != DT_REG)
|
||||
if (validate_old_timelog(dp, logfname, &tm) == 0)
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* We should now have old an old rotated logfile, so
|
||||
* add it to the 'list'.
|
||||
@ -2260,13 +2275,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;
|
||||
@ -2295,14 +2363,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 */
|
||||
|
Loading…
Reference in New Issue
Block a user