1 diff -u -ruN logrotate-3.7.1.orig/config.c logrotate-3.7.1/config.c
2 --- logrotate-3.7.1.orig/config.c 2003-08-07 07:13:14.000000000 -0400
3 +++ logrotate-3.7.1/config.c 2005-05-24 12:21:09.000000000 -0400
5 newlog->flags &= ~LOG_FLAG_IFEMPTY;
7 *endtag = oldchar, start = endtag;
8 + } else if (!strcmp(start, "dateext")) {
9 + newlog->flags |= LOG_FLAG_DATEEXT;
11 + *endtag = oldchar, start = endtag;
12 + } else if (!strcmp(start, "nodateext")) {
13 + newlog->flags &= ~LOG_FLAG_DATEEXT;
15 + *endtag = oldchar, start = endtag;
16 } else if (!strcmp(start, "noolddir")) {
17 newlog->oldDir = NULL;
21 *endtag = oldchar, start = endtag;
23 + } else if (!strcmp(start, "maxage")) {
24 + *endtag = oldchar, start = endtag;
26 + if (!isolateValue(configFile, lineNum, "maxage count", &start,
28 + oldchar = *endtag, *endtag = '\0';
30 + newlog->rotateAge = strtoul(start, &chptr, 0);
31 + if (*chptr || newlog->rotateAge < 0) {
32 + message(MESS_ERROR, "%s:%d bad maximum age '%s'\n",
33 + configFile, lineNum, start);
36 + *endtag = oldchar, start = endtag;
38 } else if (!strcmp(start, "errors")) {
39 message(MESS_DEBUG, "%s: %d: the errors directive is deprecated and no longer used.\n",
41 diff -u -ruN logrotate-3.7.1.orig/logrotate.8 logrotate-3.7.1/logrotate.8
42 --- logrotate-3.7.1.orig/logrotate.8 2003-08-07 07:13:14.000000000 -0400
43 +++ logrotate-3.7.1/logrotate.8 2005-05-24 12:21:09.000000000 -0400
45 Log files are rotated every day.
49 +Archive old versions of log files adding a daily extension like YYYYMMDD
50 +instead of simply adding a number.
54 Postpone compression of the previous log file to the next rotation cycle.
55 This has only effect when used in combination with \fBcompress\fR.
57 instead of the just-rotated file (this is the default).
60 +\fBmaxage\fR \fIcount\fR
61 +Remove rotated logs older than <count> days. The age is only checked
62 +if the logfile is to be rotated. The files are mailed to the
63 +configured address if \fBmaillast\fR and \fBmail\fR are configured.
67 If the log file is missing, go on to the next one without issuing an error
68 message. See also \fBnomissingok\fR.
69 diff -u -ruN logrotate-3.7.1.orig/logrotate.c logrotate-3.7.1/logrotate.c
70 --- logrotate-3.7.1.orig/logrotate.c 2004-10-19 17:41:24.000000000 -0400
71 +++ logrotate-3.7.1/logrotate.c 2005-05-24 12:21:09.000000000 -0400
79 #include <selinux/selinux.h>
82 #include "logrotate.h"
84 +#if !defined(GLOB_ABORTED) && defined(GLOB_ABEND)
85 +#define GLOB_ABORTED GLOB_ABEND
90 struct tm lastRotated; /* only tm.mon, tm_mday, tm_year are good! */
92 char * mailCommand = DEFAULT_MAIL_COMMAND;
95 +static int globerr(const char * pathname, int theerr) {
96 + message(MESS_ERROR, "error accessing %s: %s\n", pathname,
99 + /* We want the glob operation to continue, so return 0 */
103 static logState * findState(const char * fn, struct stateSet * sip) {
105 logState * states = sip->states;
107 struct tm now = *localtime(&nowSecs);
110 + /* find the filename fn in the statesPtr list */
111 for (i = 0; i < numStates; i++)
112 if (!strcmp(fn, states[i].fn)) break;
114 + /* not in statesPtr list, so add new entry */
115 if (i == numStates) {
117 states = realloc(states, sizeof(*states) * numStates);
122 +static int removeLogFile(char * name) {
123 + message(MESS_DEBUG, "removing old log %s\n", name);
125 + if (!debug && unlink(name)) {
126 + message(MESS_ERROR, "Failed to remove old log %s: %s\n",
127 + name, strerror(errno));
133 static int compressLogFile(char * name, logInfo * log, struct stat *sb) {
134 char * compressedName;
135 const char ** fullCommand;
140 +static int mailLogWrapper (char * mailFilename, char * mailCommand, int logNum, logInfo * log) {
141 + /* if the log is compressed (and we're not mailing a
142 + * file whose compression has been delayed), we need
143 + * to uncompress it */
144 + if ((log->flags & LOG_FLAG_COMPRESS) &&
145 + !((log->flags & LOG_FLAG_DELAYCOMPRESS) &&
146 + (log->flags & LOG_FLAG_MAILFIRST))) {
147 + if (mailLog(mailFilename, mailCommand,
148 + log->uncompress_prog, log->logAddress,
149 + log->files[logNum]))
152 + if (mailLog(mailFilename, mailCommand, NULL,
153 + log->logAddress, mailFilename))
159 static int copyTruncate(char * currLog, char * saveLog, struct stat * sb, int flags) {
161 int fdcurr = -1, fdsave = -1;
166 + char * glob_pattern;
170 int rotateCount = log->rotateCount ? log->rotateCount : 1;
171 int logStart = (log->logStart == -1) ? 1 : log->logStart;
174 alloc_size = strlen(dirName) + strlen(baseName) +
175 strlen(log->files[logNum]) + strlen(fileext) +
176 - strlen(compext) + 10;
177 + strlen(compext) + 18;
179 oldName = alloca(alloc_size);
180 newName = alloca(alloc_size);
181 @@ -531,16 +579,116 @@
182 /* First compress the previous log when necessary */
183 if (log->flags & LOG_FLAG_COMPRESS &&
184 log->flags & LOG_FLAG_DELAYCOMPRESS) {
185 - struct stat sbprev;
187 - sprintf(oldName, "%s/%s.%d%s", dirName, baseName, logStart, fileext);
188 - if (stat(oldName, &sbprev)) {
189 - message(MESS_DEBUG, "previous log %s does not exist\n",
192 - hasErrors = compressLogFile(oldName, log, &sbprev);
193 + if (log->flags & LOG_FLAG_DATEEXT) {
194 + /* glob for uncompressed files with our pattern */
195 + glob_pattern = malloc(strlen(dirName) + strlen(baseName)
196 + + strlen(fileext) + 44 );
197 + sprintf(glob_pattern,
198 + "%s/%s-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%s",
199 + dirName, baseName, fileext);
200 + rc = glob(glob_pattern, 0, globerr, &globResult);
201 + if (!rc && globResult.gl_pathc > 0) {
202 + for (i = 0; i < globResult.gl_pathc && !hasErrors; i++) {
203 + struct stat sbprev;
204 + sprintf(oldName,"%s",(globResult.gl_pathv)[i]);
205 + if (stat(oldName, &sbprev)) {
206 + message(MESS_DEBUG, "previous log %s does not exist\n", oldName);
208 + hasErrors = compressLogFile(oldName, log, &sbprev);
212 + message (MESS_DEBUG, "glob finding logs to compress failed\n");
213 + /* fallback to old behaviour */
214 + sprintf(oldName, "%s/%s.%d%s", dirName, baseName, logStart, fileext);
216 + globfree(&globResult);
217 + free(glob_pattern);
219 + struct stat sbprev;
221 + sprintf(oldName, "%s/%s.%d%s", dirName, baseName, logStart, fileext);
222 + if (stat(oldName, &sbprev)) {
223 + message(MESS_DEBUG, "previous log %s does not exist\n",
226 + hasErrors = compressLogFile(oldName, log, &sbprev);
231 + firstRotated = alloca(strlen(dirName) + strlen(baseName) +
232 + strlen(fileext) + strlen(compext) + 30);
234 + if(log->flags & LOG_FLAG_DATEEXT) {
235 + /* glob for compressed files with our pattern
236 + * and compress ext */
237 + glob_pattern = malloc(strlen(dirName)+strlen(baseName)
238 + +strlen(fileext)+strlen(compext)+44);
239 + sprintf(glob_pattern,
240 + "%s/%s-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%s%s",
241 + dirName, baseName, fileext, compext);
242 + rc = glob(glob_pattern, 0, globerr, &globResult);
244 + /* search for files to drop, if we find one remember it,
245 + * if we find another one mail and remove the first and
246 + * remember the second and so on */
247 + struct stat fst_buf;
249 + /* remove the first (n - rotateCount) matches
250 + * no real rotation needed, since the files have
251 + * the date in their name */
252 + for (i = 0; i < globResult.gl_pathc; i++) {
253 + if( !stat((globResult.gl_pathv)[i],&fst_buf) ) {
254 + if ((i <= ((int)globResult.gl_pathc - rotateCount))
255 + || ((log->rotateAge > 0)
256 + && (((nowSecs - fst_buf.st_mtime)/60/60/24)
257 + > log->rotateAge))) {
258 + if ( mail_out != -1 ) {
259 + if (!hasErrors && log->logAddress) {
260 + char * mailFilename = (globResult.gl_pathv)[mail_out];
261 + hasErrors = mailLogWrapper(mailFilename, mailCommand, logNum, log);
263 + hasErrors = removeLogFile(mailFilename);
270 + if ( mail_out != -1 ) {
271 + /* oldName is oldest Backup found (for unlink later) */
272 + sprintf(oldName, "%s", (globResult.gl_pathv)[mail_out]);
273 + strcpy(disposeName, oldName);
275 + disposeName = NULL;
277 + message (MESS_DEBUG, "glob finding old rotated logs failed\n");
278 + disposeName = NULL;
280 + /* firstRotated is most recently created/compressed rotated log */
281 + sprintf(firstRotated, "%s/%s-%04d%02d%02d%s%s",
282 + dirName, baseName, now.tm_year+1900,
283 + now.tm_mon+1, now.tm_mday, fileext, compext);
284 + globfree(&globResult);
285 + free(glob_pattern);
287 + if ( log->rotateAge ) {
288 + struct stat fst_buf;
289 + for (i=1; i <= rotateCount; i++) {
290 + sprintf(oldName, "%s/%s.%d%s%s", dirName, baseName,
291 + rotateCount + 1, fileext, compext);
292 + if(!stat(oldName,&fst_buf)
293 + && (((nowSecs - fst_buf.st_mtime)/60/60/24)
294 + > log->rotateAge)) {
295 + char * mailFilename = (globResult.gl_pathv)[i];
296 + if (!hasErrors && log->logAddress)
297 + hasErrors = mailLogWrapper(mailFilename, mailCommand, logNum, log);
299 + hasErrors = removeLogFile(mailFilename);
304 sprintf(oldName, "%s/%s.%d%s%s", dirName, baseName,
305 logStart + rotateCount, fileext, compext);
308 strcpy(disposeName, oldName);
310 - firstRotated = alloca(strlen(dirName) + strlen(baseName) +
311 - strlen(fileext) + strlen(compext) + 30);
312 sprintf(firstRotated, "%s/%s.%d%s%s", dirName, baseName,
314 (log->flags & LOG_FLAG_DELAYCOMPRESS) ? "" : compext);
315 @@ -600,12 +746,27 @@
320 + } /* !LOG_FLAG_DATEEXT */
324 - /* note: the gzip extension is *not* used here! */
325 - sprintf(finalName, "%s/%s.%d%s", dirName, baseName, logStart, fileext);
328 + if(log->flags & LOG_FLAG_DATEEXT) {
329 + char * destFile = alloca(strlen(dirName) + strlen(baseName) +
330 + strlen(fileext) + strlen(compext) + 30);
331 + struct stat fst_buf;
332 + sprintf(finalName, "%s/%s-%04d%02d%02d%s",
333 + dirName, baseName, now.tm_year+1900,
334 + now.tm_mon+1, now.tm_mday, fileext);
335 + sprintf(destFile, "%s%s", finalName, compext);
336 + if(!stat(destFile,&fst_buf)) {
337 + message (MESS_DEBUG, "destination %s already exists, skipping rotation\n", firstRotated);
341 + /* note: the gzip extension is *not* used here! */
342 + sprintf(finalName, "%s/%s.%d%s", dirName, baseName, logStart, fileext);
345 /* if the last rotation doesn't exist, that's okay */
346 if (!debug && access(disposeName, F_OK)) {
347 message(MESS_DEBUG, "log %s doesn't exist -- won't try to "
356 if (log->pre && !(log->flags & LOG_FLAG_SHAREDSCRIPTS)) {
357 message(MESS_DEBUG, "running prerotate script\n");
358 @@ -722,33 +880,12 @@
360 mailFilename = disposeName;
362 - if (mailFilename) {
363 - /* if the log is compressed (and we're not mailing a
364 - file whose compression has been delayed), we need
365 - to uncompress it */
366 - if ((log->flags & LOG_FLAG_COMPRESS) &&
367 - !((log->flags & LOG_FLAG_DELAYCOMPRESS) &&
368 - (log->flags & LOG_FLAG_MAILFIRST))) {
369 - if (mailLog(mailFilename, mailCommand,
370 - log->uncompress_prog, log->logAddress,
371 - log->files[logNum]))
374 - if (mailLog(mailFilename, mailCommand, NULL,
375 - log->logAddress, mailFilename))
380 + hasErrors = mailLogWrapper(mailFilename, mailCommand, logNum, log);
383 if (!hasErrors && disposeName) {
384 - message(MESS_DEBUG, "removing old log %s\n", disposeName);
386 - if (!debug && unlink(disposeName)) {
387 - message(MESS_ERROR, "Failed to remove old log %s: %s\n",
388 - disposeName, strerror(errno));
391 + hasErrors = removeLogFile(disposeName);
404 @@ -1047,7 +1186,9 @@
406 int main(int argc, const char ** argv) {
407 logInfo defConfig = { NULL, NULL, 0, NULL, ROT_SIZE,
408 - /* threshHold */ 1024 * 1024, 0,
409 + /* threshHold */ 1024 * 1024,
410 + /* rotateCount */ 0,
413 /* pre, post */ NULL, NULL,
414 /* first, last */ NULL, NULL,
415 diff -u -ruN logrotate-3.7.1.orig/logrotate.h logrotate-3.7.1/logrotate.h
416 --- logrotate-3.7.1.orig/logrotate.h 2003-08-07 07:13:14.000000000 -0400
417 +++ logrotate-3.7.1/logrotate.h 2005-05-24 12:21:09.000000000 -0400
419 #define LOG_FLAG_MAILFIRST (1 << 6)
420 #define LOG_FLAG_SHAREDSCRIPTS (1 << 7)
421 #define LOG_FLAG_COPY (1 << 8)
422 +#define LOG_FLAG_DATEEXT (1 << 9)
424 #define NO_FORCE_ROTATE 0
425 #define FORCE_ROTATE 1
427 enum { ROT_DAYS, ROT_WEEKLY, ROT_MONTHLY, ROT_SIZE, ROT_FORCE } criterium;
428 unsigned int threshhold;
432 char * pre, * post, * first, * last;