]> git.ipfire.org Git - thirdparty/sarg.git/blame - lastlog.c
Merge the messages about invalid data
[thirdparty/sarg.git] / lastlog.c
CommitLineData
25697a35 1/*
94ff9470 2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
110ce984 3 * 1998, 2015
25697a35
GS
4 *
5 * SARG donations:
6 * please look at http://sarg.sourceforge.net/donations.php
1164c474
FM
7 * Support:
8 * http://sourceforge.net/projects/sarg/forums/forum/363374
25697a35
GS
9 * ---------------------------------------------------------------------
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
24 *
25 */
26
27#include "include/conf.h"
5f3cfd1d 28#include "include/defs.h"
25697a35 29
0971b2d6
FM
30struct DirEntry
31{
32 struct DirEntry *Next;
33 time_t Time;
34 char *Name;
35};
36
37static void DeleteDirList(struct DirEntry *List)
38{
39 struct DirEntry *Next;
40
41 while (List)
42 {
43 Next=List->Next;
44 if (List->Name) free(List->Name);
45 free(List);
46 List=Next;
47 }
48}
49
50static struct DirEntry *AppendDirEntry(struct DirEntry *List,time_t CreationTime,const char *Name,int NameLen)
51{
52 struct DirEntry *entry;
53 struct DirEntry *prev;
54 struct DirEntry *ptr;
55
56 entry=malloc(sizeof(*entry));
57 if (!entry) {
58 debuga(_("Not enough memory to store a report to purge\n"));
59 DeleteDirList(List);
60 return(NULL);
61 }
62 entry->Name=malloc((NameLen+1)*sizeof(char));
63 if (!entry->Name) {
64 free(entry);
65 debuga(_("Not enough memory to store a report to purge\n"));
66 DeleteDirList(List);
67 return(NULL);
68 }
69 entry->Time=CreationTime;
70 strcpy(entry->Name,Name);
71
72 // store most recent file first
73 prev=NULL;
74 for (ptr=List ; ptr ; ptr=ptr->Next)
75 {
76 if (ptr->Time>CreationTime) break;
77 prev=ptr;
78 }
79 entry->Next=ptr;
80 if (prev)
81 prev->Next=entry;
82 else
83 List=entry;
84
85 return(List);
86}
87
16c12388
FM
88static struct DirEntry *BuildDirDateList(struct DirEntry *List,char *Path,int PathSize,int RootPos,int Length,int Level)
89{
90 DIR *dirp;
91 struct dirent *direntp;
92 struct stat statb;
93 int name_len;
94
95 if ((dirp = opendir(Path)) == NULL) {
cd012e70 96 debuga(_("Cannot open directory \"%s\": %s\n"),Path,strerror(errno));
16c12388
FM
97 exit(EXIT_FAILURE);
98 }
99 while ((direntp = readdir( dirp )) != NULL )
100 {
101 name_len=strlen(direntp->d_name);
102 if (RootPos+name_len+1>=PathSize) {
103 debuga(_("Directory entry too long to purge the old reports: %s%s\n"),Path,direntp->d_name);
104 exit(EXIT_FAILURE);
105 }
106 strcpy(Path+Length,direntp->d_name);
107 if (stat(Path,&statb) == -1) {
108 debuga(_("Failed to get the last modification time of %s\n"),Path);
109 continue;
110 }
111 if (!S_ISDIR(statb.st_mode)) continue;
112 if (Level==0)
113 {
114 if (IsTreeMonthFileName(direntp->d_name))
115 {
116 Path[Length+name_len]='/';
117 Path[Length+name_len+1]='\0';
118 List=BuildDirDateList(List,Path,PathSize,RootPos,Length+name_len+1,1);
119 if (!List)
120 {
121 debuga(_("Old reports deletion not undertaken due to previous error\n"));
122 break;
123 }
124 }
125 }
126 else if (Level==1)
127 {
128 if (IsTreeDayFileName(direntp->d_name))
129 {
130 List=AppendDirEntry(List,statb.st_mtime,Path+RootPos,Length-RootPos+name_len);
131 if (!List)
132 {
133 debuga(_("Old reports deletion not undertaken due to previous error\n"));
134 break;
135 }
136 }
137 }
138 }
139
140 closedir(dirp);
141 return(List);
142}
143
0971b2d6 144static struct DirEntry *BuildDirList(const char *Path)
25697a35 145{
9bd92830
FM
146 DIR *dirp;
147 struct dirent *direntp;
9bd92830 148 struct stat statb;
0971b2d6
FM
149 char warea[MAXLEN];
150 int name_pos;
151 int name_len;
152 struct DirEntry *List=NULL;
9bd92830 153
0971b2d6
FM
154 name_pos=strlen(Path);
155 if (name_pos>=sizeof(warea)) {
156 debuga(_("The directory containing the old reports to purge is too long: %s\n"),Path);
007905af 157 exit(EXIT_FAILURE);
9bd92830 158 }
0971b2d6 159 strcpy(warea,Path);
9bd92830 160 if ((dirp = opendir(outdir)) == NULL) {
cd012e70 161 debuga(_("Cannot open directory \"%s\": %s\n"),outdir,strerror(errno));
9bd92830
FM
162 exit(EXIT_FAILURE);
163 }
0971b2d6
FM
164 while ((direntp = readdir( dirp )) != NULL )
165 {
0971b2d6
FM
166 name_len=strlen(direntp->d_name);
167 if (name_pos+name_len+1>=sizeof(warea)) {
168 debuga(_("Directory entry too long to purge the old reports: %s%s\n"),Path,direntp->d_name);
169 exit(EXIT_FAILURE);
170 }
171 strcpy(warea+name_pos,direntp->d_name);
9bd92830 172 if (stat(warea,&statb) == -1) {
0971b2d6 173 debuga(_("Failed to get the last modification time of %s\n"),warea);
9bd92830
FM
174 continue;
175 }
16c12388
FM
176 if (!S_ISDIR(statb.st_mode)) continue;
177 if (IsTreeFileDirName(direntp->d_name))
0971b2d6 178 {
16c12388
FM
179 List=AppendDirEntry(List,statb.st_mtime,direntp->d_name,name_len);
180 if (!List)
181 {
182 debuga(_("Old reports deletion not undertaken due to previous error\n"));
183 break;
184 }
185 }
186 else if (IsTreeYearFileName(direntp->d_name))
187 {
188 warea[name_pos+name_len]='/';
189 warea[name_pos+name_len+1]='\0';
190 List=BuildDirDateList(List,warea,sizeof(warea),name_pos,name_pos+name_len+1,0);
191 if (!List)
192 {
193 debuga(_("Old reports deletion not undertaken due to previous error\n"));
194 break;
195 }
0971b2d6 196 }
9bd92830
FM
197 }
198
0971b2d6
FM
199 closedir(dirp);
200 return(List);
201}
202
16c12388
FM
203static void DeleteEmptyDirs(char *Path,int PathSize,int BasePos)
204{
205 char *Dir;
206 DIR *dirp;
207 struct dirent *direntp;
208 bool index;
209
210 while ((Dir=strrchr(Path,'/'))!=NULL)
211 {
212 if (Dir-Path<=BasePos) break;
213 *Dir='\0';
214 if ((dirp = opendir(Path)) == NULL) {
cd012e70 215 debuga(_("Cannot open directory \"%s\": %s\n"),Path,strerror(errno));
16c12388
FM
216 return;
217 }
218 index=false;
219 while ((direntp = readdir( dirp )) != NULL )
220 {
221 if (direntp->d_name[0]=='.' && (direntp->d_name[1]=='\0' || (direntp->d_name[1]=='.' && direntp->d_name[2]=='\0'))) continue;
222 if (!strcmp(direntp->d_name,INDEX_HTML_FILE))
223 {
224 index=true;
225 continue;
226 }
227 break;
228 }
229 closedir(dirp);
230 if (direntp!=NULL) {
231 // at least one file exists in the directory, don't delete the directory
232 break;
233 }
234 if (debug)
235 debuga(_("Deleting empty directory %s\n"),Path);
236 if (index) {
237 if (strlen(Path)+strlen(INDEX_HTML_FILE)+2>=PathSize) {
70ca3381 238 debuga(_("Buffer too small to delete index file %s/%s"),Path,INDEX_HTML_FILE);
16c12388
FM
239 exit(EXIT_FAILURE);
240 }
241 strcat(Path,"/"INDEX_HTML_FILE);
242 if (unlink(Path)==-1) {
243 // TRANSLATORS: The %s at the end is the system error message describing the reason for the failure.
244 debuga(_("Failed to delete index file \"%s\" in the empty report directory: %s\n"),Path,strerror(errno));
245 exit(EXIT_FAILURE);
246 }
247 *Dir='\0';
248 }
249 if (rmdir(Path)) {
250 debuga(_("Cannot delete \"%s\": %s\n"),Path,strerror(errno));
251 exit(EXIT_FAILURE);
252 }
253 }
254 //! \todo Rebuild the surviving index file
255}
256
0971b2d6
FM
257void mklastlog(const char *outdir)
258{
259 char warea[MAXLEN];
260 int name_pos;
261 int ftot=0;
262 struct DirEntry *List;
263 struct DirEntry *ptr;
264
265 if(LastLog <= 0)
266 return;
267
268 List=BuildDirList(outdir);
269 if (!List) return;
270
271 for (ptr=List ; ptr ; ptr=ptr->Next) ftot++;
272 if (debug)
273 debuga(ngettext("%d report directory found\n","%d report directories found\n",ftot),ftot);
9bd92830 274
0428e5fd 275 if(ftot<=LastLog) {
0971b2d6 276 DeleteDirList(List);
0428e5fd
FM
277 if (debug) {
278 debuga(ngettext("No old reports to delete as only %d report currently exists\n",
279 "No old reports to delete as only %d reports currently exist\n",ftot),ftot);
280 }
0428e5fd
FM
281 return;
282 }
283
9bd92830 284 ftot-=LastLog;
0428e5fd
FM
285 if (debug)
286 debuga(ngettext("%d old report to delete\n","%d old reports to delete\n",ftot),ftot);
9bd92830 287
0971b2d6
FM
288 name_pos=strlen(outdir);
289 if (name_pos>=sizeof(warea)) {
290 DeleteDirList(List);
291 debuga(_("The directory containing the old reports to purge is too long: %s\n"),outdir);
007905af 292 exit(EXIT_FAILURE);
9bd92830 293 }
0971b2d6
FM
294 strcpy(warea,outdir);
295 for (ptr=List ; ptr && ftot>0 ; ptr=ptr->Next)
296 {
9bd92830 297 if(debug)
0971b2d6
FM
298 debuga(_("Removing old report file %s\n"),ptr->Name);
299 if (name_pos+strlen(ptr->Name)+1>=sizeof(warea)) {
300 DeleteDirList(List);
041018b6
FM
301 debuga(_("Path too long: "));
302 debuga_more("%s%s\n",outdir,ptr->Name);
9bd92830
FM
303 exit(EXIT_FAILURE);
304 }
0971b2d6 305 strcpy(warea+name_pos,ptr->Name);
1ed866e0 306 unlinkdir(warea,0);
16c12388 307 DeleteEmptyDirs(warea,sizeof(warea),name_pos);
9bd92830
FM
308 ftot--;
309 }
310
0971b2d6 311 DeleteDirList(List);
9bd92830 312 return;
25697a35 313}