Rename patches to match conventions, second round; *ouch*
[packages.git] / utils / logrotate / patches / 01-dateext_maxage.patch
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
4 @@ -511,6 +511,14 @@
5                 newlog->flags &= ~LOG_FLAG_IFEMPTY;
6  
7                 *endtag = oldchar, start = endtag;
8 +           } else if (!strcmp(start, "dateext")) {
9 +               newlog->flags |= LOG_FLAG_DATEEXT;
10 +
11 +               *endtag = oldchar, start = endtag;
12 +           } else if (!strcmp(start, "nodateext")) {
13 +               newlog->flags &= ~LOG_FLAG_DATEEXT;
14 +
15 +               *endtag = oldchar, start = endtag;
16             } else if (!strcmp(start, "noolddir")) {
17                 newlog->oldDir = NULL;
18  
19 @@ -670,6 +678,21 @@
20                     }
21                     *endtag = oldchar, start = endtag;
22                 }
23 +           } else if (!strcmp(start, "maxage")) {
24 +               *endtag = oldchar, start = endtag;
25 +
26 +               if (!isolateValue(configFile, lineNum, "maxage count", &start,
27 +                                 &endtag)) {
28 +                   oldchar = *endtag, *endtag = '\0';
29 +
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);
34 +                       return 1;
35 +                   }
36 +                   *endtag = oldchar, start = endtag;
37 +               }
38             } else if (!strcmp(start, "errors")) {
39                 message(MESS_DEBUG, "%s: %d: the errors directive is deprecated and no longer used.\n",
40                         configFile, lineNum);
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
44 @@ -200,6 +200,11 @@
45  Log files are rotated every day.
46  
47  .TP
48 +\fBdateext\fR
49 +Archive old versions of log files adding a daily extension like YYYYMMDD
50 +instead of simply adding a number.
51 +
52 +.TP
53  \fBdelaycompress\fR
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.
56 @@ -246,6 +251,12 @@
57  instead of the just-rotated file (this is the default).
58  
59  .TP
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.
64 +
65 +.TP
66  \fBmissingok\fR
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
72 @@ -11,6 +11,7 @@
73  #include <sys/wait.h>
74  #include <time.h>
75  #include <unistd.h>
76 +#include <glob.h>
77  
78  #ifdef WITH_SELINUX
79  #include <selinux/selinux.h>
80 @@ -22,6 +23,10 @@
81  #include "log.h"
82  #include "logrotate.h"
83  
84 +#if !defined(GLOB_ABORTED) && defined(GLOB_ABEND)
85 +#define GLOB_ABORTED GLOB_ABEND
86 +#endif
87 +
88  typedef struct {
89      char * fn;
90      struct tm lastRotated;     /* only tm.mon, tm_mday, tm_year are good! */
91 @@ -42,6 +47,14 @@
92  char * mailCommand = DEFAULT_MAIL_COMMAND;
93  time_t nowSecs = 0;
94  
95 +static int globerr(const char * pathname, int theerr) {
96 +    message(MESS_ERROR, "error accessing %s: %s\n", pathname,
97 +       strerror(theerr));
98 +
99 +    /* We want the glob operation to continue, so return 0 */
100 +    return 1;
101 +}
102 +
103  static logState * findState(const char * fn, struct stateSet * sip) {
104      int i;
105      logState * states = sip->states;
106 @@ -49,9 +62,11 @@
107      struct tm now = *localtime(&nowSecs);
108      time_t lr_time;
109  
110 +    /* find the filename fn in the statesPtr list */
111      for (i = 0; i < numStates; i++) 
112         if (!strcmp(fn, states[i].fn)) break;
113  
114 +    /* not in statesPtr list, so add new entry */
115      if (i == numStates) {
116         i = numStates++;
117         states = realloc(states, sizeof(*states) * numStates);
118 @@ -121,6 +136,17 @@
119      return rc;
120  }
121  
122 +static int removeLogFile(char * name) {
123 +    message(MESS_DEBUG, "removing old log %s\n", name);
124 +
125 +    if (!debug && unlink(name)) {
126 +       message(MESS_ERROR, "Failed to remove old log %s: %s\n",
127 +               name, strerror(errno));
128 +       return 1;
129 +    }
130 +    return 0;
131 +}
132 +
133  static int compressLogFile(char * name, logInfo * log, struct stat *sb) {
134      char * compressedName;
135      const char ** fullCommand;
136 @@ -265,6 +291,25 @@
137      return rc;
138  }
139  
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]))
150 +           return 1;
151 +    } else {
152 +       if (mailLog(mailFilename, mailCommand, NULL,
153 +                   log->logAddress, mailFilename))
154 +           return 1;
155 +    }
156 +    return 0;
157 +}
158 +
159  static int copyTruncate(char * currLog, char * saveLog, struct stat * sb, int flags) {
160      char buf[BUFSIZ];
161      int fdcurr = -1, fdsave = -1;
162 @@ -479,6 +524,9 @@
163      char * baseName;
164      char * dirName;
165      char * firstRotated;
166 +    char * glob_pattern;
167 +    glob_t globResult;
168 +    int rc;
169      size_t alloc_size;
170      int rotateCount = log->rotateCount ? log->rotateCount : 1;
171      int logStart = (log->logStart == -1) ? 1 : log->logStart;
172 @@ -509,7 +557,7 @@
173  
174      alloc_size = strlen(dirName) + strlen(baseName) + 
175                   strlen(log->files[logNum]) + strlen(fileext) +
176 -                 strlen(compext) + 10;
177 +                 strlen(compext) + 18;
178      
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;
186 -       
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",
190 -                   oldName);
191 -        } else {
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);
207 +                   } else {
208 +                       hasErrors = compressLogFile(oldName, log, &sbprev);
209 +                   }
210 +               }
211 +           } else {
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);
215 +           }
216 +           globfree(&globResult);
217 +           free(glob_pattern);
218 +       } else {
219 +           struct stat sbprev;
220 +
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",
224 +                       oldName);
225 +           } else {
226 +               hasErrors = compressLogFile(oldName, log, &sbprev);
227 +           }
228         }
229      }
230 +
231 +    firstRotated = alloca(strlen(dirName) + strlen(baseName) +
232 +                         strlen(fileext) + strlen(compext) + 30);
233 +
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);
243 +       if (!rc) {
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;
248 +           int mail_out = -1;
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);
262 +                               if (!hasErrors)
263 +                                   hasErrors = removeLogFile(mailFilename);
264 +                           }
265 +                       }
266 +                       mail_out = i;
267 +                   }
268 +               }
269 +           }
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);
274 +           } else
275 +               disposeName = NULL;
276 +       } else {
277 +           message (MESS_DEBUG, "glob finding old rotated logs failed\n");
278 +           disposeName = NULL;
279 +       }
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);
286 +    } else {
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);
298 +                   if (!hasErrors)
299 +                       hasErrors = removeLogFile(mailFilename);
300 +               }
301 +           }
302 +       }
303      
304      sprintf(oldName, "%s/%s.%d%s%s", dirName, baseName,
305              logStart + rotateCount, fileext, compext);
306 @@ -548,8 +696,6 @@
307      
308      strcpy(disposeName, oldName);
309      
310 -    firstRotated = alloca(strlen(dirName) + strlen(baseName) +
311 -                          strlen(fileext) + strlen(compext) + 30);
312      sprintf(firstRotated, "%s/%s.%d%s%s", dirName, baseName,
313              logStart, fileext, 
314             (log->flags & LOG_FLAG_DELAYCOMPRESS) ? "" : compext);
315 @@ -600,12 +746,27 @@
316             }
317         }
318      }
319 -    
320 +    } /* !LOG_FLAG_DATEEXT */
321
322      finalName = oldName;
323 -    
324 -    /* note: the gzip extension is *not* used here! */
325 -    sprintf(finalName, "%s/%s.%d%s", dirName, baseName, logStart, fileext);
326 -    
327 +
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);
338 +           hasErrors = 1;
339 +       }
340 +    } else {
341 +       /* note: the gzip extension is *not* used here! */
342 +       sprintf(finalName, "%s/%s.%d%s", dirName, baseName, logStart, fileext);
343 +    }
344
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 "
348 @@ -613,9 +774,6 @@
349          disposeName = NULL;
350      } 
351      
352 -    free(dirName);
353 -    free(baseName);
354 -    
355      if (!hasErrors) {
356          if (log->pre && !(log->flags & LOG_FLAG_SHAREDSCRIPTS)) {
357              message(MESS_DEBUG, "running prerotate script\n");
358 @@ -722,33 +880,12 @@
359              else
360                  mailFilename = disposeName;
361  
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])) 
372 -                       hasErrors = 1;
373 -               } else {
374 -                   if (mailLog(mailFilename, mailCommand, NULL, 
375 -                               log->logAddress, mailFilename))
376 -                       hasErrors = 1;
377 -               }
378 -           }
379 +            if (mailFilename)
380 +               hasErrors = mailLogWrapper(mailFilename, mailCommand, logNum, log);
381          }
382         
383          if (!hasErrors && disposeName) {
384 -            message(MESS_DEBUG, "removing old log %s\n", disposeName);
385 -           
386 -            if (!debug && unlink(disposeName)) {
387 -                message(MESS_ERROR, "Failed to remove old log %s: %s\n",
388 -                       disposeName, strerror(errno));
389 -                hasErrors = 1;
390 -           }
391 +           hasErrors = removeLogFile(disposeName);
392         }
393      }
394      
395 @@ -761,6 +898,8 @@
396           }
397         }
398  #endif
399 +    free(dirName);
400 +    free(baseName);
401      return hasErrors;
402  }
403  
404 @@ -1047,7 +1186,9 @@
405  
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,
411 +                         /* rotateAge */ 0,
412                           /* log start */ -1,
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
418 @@ -15,6 +15,7 @@
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)
423  
424  #define NO_FORCE_ROTATE 0
425  #define FORCE_ROTATE    1
426 @@ -34,6 +35,7 @@
427      enum { ROT_DAYS, ROT_WEEKLY, ROT_MONTHLY, ROT_SIZE, ROT_FORCE } criterium;
428      unsigned int threshhold;
429      int rotateCount;
430 +    int rotateAge;
431      int logStart;
432      char * pre, * post, * first, * last;
433      char * logAddress;