]>
Commit | Line | Data |
---|---|---|
8167cba5 AM |
1 | --- config.c |
2 | +++ config.c | |
3 | @@ -441,6 +441,14 @@ | |
4 | newlog->flags &= ~LOG_FLAG_IFEMPTY; | |
5 | ||
6 | *endtag = oldchar, start = endtag; | |
7 | + } else if (!strcmp(start, "dateext")) { | |
8 | + newlog->flags |= LOG_FLAG_DATEEXT; | |
9 | + | |
10 | + *endtag = oldchar, start = endtag; | |
11 | + } else if (!strcmp(start, "nodateext")) { | |
12 | + newlog->flags &= ~LOG_FLAG_DATEEXT; | |
13 | + | |
14 | + *endtag = oldchar, start = endtag; | |
15 | } else if (!strcmp(start, "noolddir")) { | |
16 | newlog->oldDir = NULL; | |
17 | ||
18 | --- logrotate.8 | |
19 | +++ logrotate.8 | |
20 | @@ -200,6 +200,11 @@ | |
21 | Log files are rotated every day. | |
22 | ||
23 | .TP | |
24 | +\fBdateext\fR | |
25 | +Archive old versions of log files adding a daily extension like YYYYMMDD | |
26 | +instead of simply adding a number. | |
27 | + | |
28 | +.TP | |
29 | \fBdelaycompress\fR | |
30 | Postpone compression of the previous log file to the next rotation cycle. | |
31 | This has only effect when used in combination with \fBcompress\fR. | |
32 | --- logrotate.c | |
33 | +++ logrotate.c | |
34 | @@ -10,6 +10,7 @@ | |
35 | #include <sys/stat.h> | |
36 | #include <time.h> | |
37 | #include <unistd.h> | |
38 | +#include <glob.h> | |
39 | ||
40 | #ifdef WITH_SELINUX | |
41 | #include <selinux/selinux.h> | |
42 | @@ -21,6 +22,10 @@ | |
43 | #include "log.h" | |
44 | #include "logrotate.h" | |
45 | ||
46 | +#if !defined(GLOB_ABORTED) && defined(GLOB_ABEND) | |
47 | +#define GLOB_ABORTED GLOB_ABEND | |
48 | +#endif | |
49 | + | |
50 | typedef struct { | |
51 | char * fn; | |
52 | struct tm lastRotated; /* only tm.mon, tm_mday, tm_year are good! */ | |
53 | @@ -64,6 +69,14 @@ | |
54 | return newstr; | |
55 | } | |
56 | ||
57 | +static int globerr(const char * pathname, int theerr) { | |
58 | + message(MESS_ERROR, "error accessing %s: %s\n", pathname, | |
59 | + strerror(theerr)); | |
60 | + | |
61 | + /* We want the glob operation to continue, so return 0 */ | |
62 | + return 1; | |
63 | +} | |
64 | + | |
65 | static logState * findState(const char * fn, logState ** statesPtr, | |
66 | int * numStatesPtr) { | |
67 | int i; | |
68 | @@ -72,9 +85,11 @@ | |
69 | struct tm now = *localtime(&nowSecs); | |
70 | time_t lr_time; | |
71 | ||
72 | + /* find the filename fn in the statesPtr list */ | |
73 | for (i = 0; i < numStates; i++) | |
74 | if (!strcmp(fn, states[i].fn)) break; | |
75 | ||
76 | + /* not in statesPtr list, so add new entry */ | |
77 | if (i == numStates) { | |
78 | i = numStates++; | |
79 | states = realloc(states, sizeof(*states) * numStates); | |
80 | @@ -465,6 +480,9 @@ | |
81 | char * baseName; | |
82 | char * dirName; | |
83 | char * firstRotated; | |
84 | + char * glob_pattern; | |
85 | + glob_t globResult; | |
86 | + int rc; | |
87 | size_t alloc_size; | |
88 | int rotateCount = log->rotateCount ? log->rotateCount : 1; | |
89 | int logStart = (log->logStart == -1) ? 1 : log->logStart; | |
90 | @@ -501,7 +519,7 @@ | |
91 | ||
92 | alloc_size = strlen(dirName) + strlen(baseName) + | |
93 | strlen(log->files[logNum]) + strlen(fileext) + | |
94 | - strlen(compext) + 10; | |
95 | + strlen(compext) + 18; | |
96 | ||
97 | oldName = alloca(alloc_size); | |
98 | newName = alloca(alloc_size); | |
99 | @@ -523,18 +541,95 @@ | |
100 | /* First compress the previous log when necessary */ | |
101 | if (log->flags & LOG_FLAG_COMPRESS && | |
102 | log->flags & LOG_FLAG_DELAYCOMPRESS) { | |
103 | - sprintf(oldName, "%s/%s.%d%s", dirName, baseName, logStart, fileext); | |
104 | - hasErrors = compress_log(log, oldName, "previous", errorFile); | |
105 | + if(log->flags & LOG_FLAG_DATEEXT) { | |
106 | + /* glob for uncompressed files with our pattern */ | |
107 | + glob_pattern = malloc(strlen(dirName) + strlen(baseName) | |
108 | + + strlen(fileext) + 44 ); | |
109 | + sprintf(glob_pattern, | |
110 | + "%s/%s-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%s", | |
111 | + dirName, baseName, fileext); | |
112 | + rc = glob(glob_pattern, 0, globerr, &globResult); | |
113 | + if (!rc && globResult.gl_pathc > 0) { | |
114 | + for (i = 0; i < globResult.gl_pathc && !hasErrors; i++) { | |
115 | + sprintf(oldName,"%s",(globResult.gl_pathv)[i]); | |
116 | + hasErrors = compress_log(log, oldName, "previous", errorFile); | |
117 | + } | |
118 | + } else { | |
119 | + message (MESS_DEBUG, "glob finding logs to compress failed\n"); | |
120 | + /* fallback to old behaviour */ | |
121 | + sprintf(oldName, "%s/%s.%d%s", dirName, baseName, logStart, fileext); | |
122 | + } | |
123 | + globfree(&globResult); | |
124 | + free(glob_pattern); | |
125 | + } else { | |
126 | + sprintf(oldName, "%s/%s.%d%s", dirName, baseName, logStart, fileext); | |
127 | + hasErrors = compress_log(log, oldName, "previous", errorFile); | |
128 | + } | |
129 | } | |
130 | - | |
131 | + firstRotated = alloca(strlen(dirName) + strlen(baseName) + | |
132 | + strlen(fileext) + strlen(compext) + 30); | |
133 | + | |
134 | + if(log->flags & LOG_FLAG_DATEEXT) { | |
135 | + /* glob for compressed files with our pattern | |
136 | + * and compress ext */ | |
137 | + glob_pattern = malloc(strlen(dirName)+strlen(baseName) | |
138 | + +strlen(fileext)+strlen(compext)+44); | |
139 | + sprintf(glob_pattern, | |
140 | + "%s/%s-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%s%s", | |
141 | + dirName, baseName, fileext, compext); | |
142 | + rc = glob(glob_pattern, 0, globerr, &globResult); | |
143 | + if (!rc) { | |
144 | + /* search for files to drop, if we find one remember it, | |
145 | + * if we find another one mail and remove the first and | |
146 | + * remember the second and so on */ | |
147 | + struct stat fst_buf; | |
148 | + int mail_out = -1; | |
149 | + /* remove the first (n - rotateCount) matches | |
150 | + * no real rotation needed, since the files have | |
151 | + * the date in their name */ | |
152 | + for (i = 0; i < globResult.gl_pathc; i++) { | |
153 | + if( !stat((globResult.gl_pathv)[i],&fst_buf) ) { | |
154 | + if (i < ((int)globResult.gl_pathc - rotateCount - 1)) { | |
155 | + if ( mail_out != -1 ) { | |
156 | + if (!hasErrors && log->logAddress) | |
157 | + hasErrors = mail_old_log(log, logNum, NULL, | |
158 | + (globResult.gl_pathv)[mail_out], | |
159 | + errorFile, compext); | |
160 | + if (!hasErrors) | |
161 | + hasErrors = remove_old_log(log, | |
162 | + (globResult.gl_pathv)[mail_out], | |
163 | + errorFile); | |
164 | + } | |
165 | + mail_out = i; | |
166 | + } | |
167 | + } | |
168 | + } | |
169 | + if ( mail_out != -1 ) { | |
170 | + /* oldName is oldest Backup found (for unlink later) */ | |
171 | + sprintf(oldName, "%s", (globResult.gl_pathv)[mail_out]); | |
172 | + strcpy(disposeName, oldName); | |
173 | + } else | |
174 | + disposeName = NULL; | |
175 | + /* firstRotated is most recently created/compressed rotated log */ | |
176 | + sprintf(firstRotated, "%s/%s-%04d%02d%02d%s%s", | |
177 | + dirName, baseName, now.tm_year+1900, | |
178 | + now.tm_mon+1, now.tm_mday, fileext, compext); | |
179 | + } else { | |
180 | + message (MESS_DEBUG, "glob finding old rotated logs failed\n"); | |
181 | + disposeName = NULL; | |
182 | + } | |
183 | + /* firstRotated is most recently created/compressed rotated log */ | |
184 | + /* copy these two out with strdup */ | |
185 | + globfree(&globResult); | |
186 | + free(glob_pattern); | |
187 | + } else { | |
188 | + | |
189 | sprintf(oldName, "%s/%s.%d%s%s", dirName, baseName, | |
190 | logStart + rotateCount, fileext, compext); | |
191 | strcpy(newName, oldName); | |
192 | ||
193 | strcpy(disposeName, oldName); | |
194 | ||
195 | - firstRotated = alloca(strlen(dirName) + strlen(baseName) + | |
196 | - strlen(fileext) + strlen(compext) + 30); | |
197 | sprintf(firstRotated, "%s/%s.%d%s%s", dirName, baseName, | |
198 | logStart, fileext, compext); | |
199 | ||
200 | @@ -584,11 +679,27 @@ | |
201 | } | |
202 | } | |
203 | } | |
204 | + } /* !LOG_FLAG_DATEEXT */ | |
205 | ||
206 | finalName = oldName; | |
207 | + | |
208 | ||
209 | - /* note: the gzip extension is *not* used here! */ | |
210 | - sprintf(finalName, "%s/%s.%d%s", dirName, baseName, logStart, fileext); | |
211 | + if(log->flags & LOG_FLAG_DATEEXT) { | |
212 | + char * destFile = alloca(strlen(dirName) + strlen(baseName) + | |
213 | + strlen(fileext) + strlen(compext) + 30); | |
214 | + struct stat fst_buf; | |
215 | + sprintf(finalName, "%s/%s-%04d%02d%02d%s", | |
216 | + dirName, baseName, now.tm_year+1900, | |
217 | + now.tm_mon+1, now.tm_mday, fileext); | |
218 | + sprintf(destFile, "%s%s", finalName, compext); | |
219 | + if(!stat(destFile,&fst_buf)) { | |
220 | + message (MESS_DEBUG, "destination %s already exists, skipping rotation\n", firstRotated); | |
221 | + hasErrors = 1; | |
222 | + } | |
223 | + } else { | |
224 | + /* note: the gzip extension is *not* used here! */ | |
225 | + sprintf(finalName, "%s/%s.%d%s", dirName, baseName, logStart, fileext); | |
226 | + } | |
227 | ||
228 | /* if the last rotation doesn't exist, that's okay */ | |
229 | if (!debug && access(disposeName, F_OK)) { | |
230 | @@ -597,9 +708,6 @@ | |
231 | disposeName = NULL; | |
232 | } | |
233 | ||
234 | - free(dirName); | |
235 | - free(baseName); | |
236 | - | |
237 | if (!hasErrors) { | |
238 | if (log->pre && !(log->flags & LOG_FLAG_SHAREDSCRIPTS)) { | |
239 | message(MESS_DEBUG, "running prerotate script\n"); | |
240 | @@ -716,6 +824,8 @@ | |
241 | } | |
242 | } | |
243 | #endif | |
244 | + free(dirName); | |
245 | + free(baseName); | |
246 | return hasErrors; | |
247 | } | |
248 | ||
249 | --- logrotate.h | |
250 | +++ logrotate.h | |
251 | @@ -15,6 +15,7 @@ | |
252 | #define LOG_FLAG_MAILFIRST (1 << 6) | |
253 | #define LOG_FLAG_SHAREDSCRIPTS (1 << 7) | |
254 | #define LOG_FLAG_COPY (1 << 8) | |
255 | +#define LOG_FLAG_DATEEXT (1 << 9) | |
256 | ||
257 | #define NO_FORCE_ROTATE 0 | |
258 | #define FORCE_ROTATE 1 |