sarg  2.4.0
About: SARG ia a Squid Analysis Report Generator.
  Fossies Dox: sarg-2.4.0.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

lastlog.c
Go to the documentation of this file.
1 /*
2  * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
3  * 1998, 2015
4  *
5  * SARG donations:
6  * please look at http://sarg.sourceforge.net/donations.php
7  * Support:
8  * http://sourceforge.net/projects/sarg/forums/forum/363374
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"
28 #include "include/defs.h"
29 
30 struct DirEntry
31 {
32  struct DirEntry *Next;
33  time_t Time;
34  char *Name;
35 };
36 
37 static 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 
50 static 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(__FILE__,__LINE__,_("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(__FILE__,__LINE__,_("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 
88 static 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) {
96  debuga(__FILE__,__LINE__,_("Cannot open directory \"%s\": %s\n"),Path,strerror(errno));
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(__FILE__,__LINE__,_("Directory entry \"%s%s\" too long to purge the old reports\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(__FILE__,__LINE__,_("Failed to get the statistics of file \"%s\": %s\n"),Path,strerror(errno));
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(__FILE__,__LINE__,_("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(__FILE__,__LINE__,_("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 
144 static struct DirEntry *BuildDirList(const char *Path)
145 {
146  DIR *dirp;
147  struct dirent *direntp;
148  struct stat statb;
149  char warea[MAXLEN];
150  int name_pos;
151  int name_len;
152  struct DirEntry *List=NULL;
153 
154  name_pos=strlen(Path);
155  if (name_pos>=sizeof(warea)) {
156  debuga(__FILE__,__LINE__,_("The directory name \"%s\" containing the old reports to purge is too long\n"),Path);
157  exit(EXIT_FAILURE);
158  }
159  strcpy(warea,Path);
160  if ((dirp = opendir(outdir)) == NULL) {
161  debuga(__FILE__,__LINE__,_("Cannot open directory \"%s\": %s\n"),outdir,strerror(errno));
162  exit(EXIT_FAILURE);
163  }
164  while ((direntp = readdir( dirp )) != NULL )
165  {
166  name_len=strlen(direntp->d_name);
167  if (name_pos+name_len+1>=sizeof(warea)) {
168  debuga(__FILE__,__LINE__,_("Directory entry \"%s%s\" too long to purge the old reports\n"),Path,direntp->d_name);
169  exit(EXIT_FAILURE);
170  }
171  strcpy(warea+name_pos,direntp->d_name);
172  if (stat(warea,&statb) == -1) {
173  debuga(__FILE__,__LINE__,_("Failed to get the statistics of file \"%s\": %s\n"),warea,strerror(errno));
174  continue;
175  }
176  if (!S_ISDIR(statb.st_mode)) continue;
177  if (IsTreeFileDirName(direntp->d_name))
178  {
179  List=AppendDirEntry(List,statb.st_mtime,direntp->d_name,name_len);
180  if (!List)
181  {
182  debuga(__FILE__,__LINE__,_("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(__FILE__,__LINE__,_("Old reports deletion not undertaken due to previous error\n"));
194  break;
195  }
196  }
197  }
198 
199  closedir(dirp);
200  return(List);
201 }
202 
203 static 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) {
215  debuga(__FILE__,__LINE__,_("Cannot open directory \"%s\": %s\n"),Path,strerror(errno));
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(__FILE__,__LINE__,_("Deleting empty directory \"%s\"\n"),Path);
236  if (index) {
237  if (strlen(Path)+strlen(INDEX_HTML_FILE)+2>=PathSize) {
238  debuga(__FILE__,__LINE__,_("Buffer too small to delete index file \"%s/%s\""),Path,INDEX_HTML_FILE);
239  exit(EXIT_FAILURE);
240  }
241  strcat(Path,"/"INDEX_HTML_FILE);
242  if (unlink(Path)==-1) {
243  debuga(__FILE__,__LINE__,_("Failed to delete \"%s\": %s\n"),Path,strerror(errno));
244  exit(EXIT_FAILURE);
245  }
246  *Dir='\0';
247  }
248  if (rmdir(Path)) {
249  debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),Path,strerror(errno));
250  exit(EXIT_FAILURE);
251  }
252  }
254 }
255 
256 void mklastlog(const char *outdir)
257 {
258  char warea[MAXLEN];
259  int name_pos;
260  int ftot=0;
261  struct DirEntry *List;
262  struct DirEntry *ptr;
263 
264  if (LastLog <= 0)
265  return;
266 
267  List=BuildDirList(outdir);
268  if (!List) return;
269 
270  for (ptr=List ; ptr ; ptr=ptr->Next) ftot++;
271  if (debug)
272  debuga(__FILE__,__LINE__,ngettext("%d report directory found\n","%d report directories found\n",ftot),ftot);
273 
274  if (ftot<=LastLog) {
275  DeleteDirList(List);
276  if (debug) {
277  debuga(__FILE__,__LINE__,ngettext("No old reports to delete as only %d report currently exists\n",
278  "No old reports to delete as only %d reports currently exist\n",ftot),ftot);
279  }
280  return;
281  }
282 
283  ftot-=LastLog;
284  if (debug)
285  debuga(__FILE__,__LINE__,ngettext("%d old report to delete\n","%d old reports to delete\n",ftot),ftot);
286 
287  name_pos=strlen(outdir);
288  if (name_pos>=sizeof(warea)) {
289  DeleteDirList(List);
290  debuga(__FILE__,__LINE__,_("The directory name \"%s\" containing the old reports to purge is too long\n"),outdir);
291  exit(EXIT_FAILURE);
292  }
293  strcpy(warea,outdir);
294  for (ptr=List ; ptr && ftot>0 ; ptr=ptr->Next)
295  {
296  if (debug)
297  debuga(__FILE__,__LINE__,_("Removing old report file %s\n"),ptr->Name);
298  if (name_pos+strlen(ptr->Name)+1>=sizeof(warea)) {
299  DeleteDirList(List);
300  debuga(__FILE__,__LINE__,_("Path too long: "));
301  debuga_more("%s%s\n",outdir,ptr->Name);
302  exit(EXIT_FAILURE);
303  }
304  strcpy(warea+name_pos,ptr->Name);
305  unlinkdir(warea,0);
306  DeleteEmptyDirs(warea,sizeof(warea),name_pos);
307  ftot--;
308  }
309 
310  DeleteDirList(List);
311  return;
312 }
debuga
void debuga(const char *File, int Line, const char *msg,...)
Definition: util.c:601
INDEX_HTML_FILE
#define INDEX_HTML_FILE
Name of the html file containing the index of a report file.
Definition: conf.h:296
outdir
char outdir[20000]
Definition: conf.h:310
LastLog
int LastLog
Definition: conf.h:320
IsTreeMonthFileName
bool IsTreeMonthFileName(const char *Name)
Definition: util.c:1368
_
#define _(String)
Definition: conf.h:155
MAXLEN
#define MAXLEN
Definition: conf.h:176
BuildDirDateList
static struct DirEntry * BuildDirDateList(struct DirEntry *List, char *Path, int PathSize, int RootPos, int Length, int Level)
Definition: lastlog.c:88
warea
char warea[20000]
Definition: conf.h:334
DeleteEmptyDirs
static void DeleteEmptyDirs(char *Path, int PathSize, int BasePos)
Definition: lastlog.c:203
unlinkdir
void unlinkdir(const char *dir, bool contentonly)
Definition: util.c:2339
DirEntry
Definition: lastlog.c:30
conf.h
Include headers and define global variables. */.
mklastlog
void mklastlog(const char *outdir)
Definition: lastlog.c:256
AppendDirEntry
static struct DirEntry * AppendDirEntry(struct DirEntry *List, time_t CreationTime, const char *Name, int NameLen)
Definition: lastlog.c:50
IsTreeDayFileName
bool IsTreeDayFileName(const char *Name)
Definition: util.c:1392
DirEntry::Name
char * Name
Definition: lastlog.c:34
BuildDirList
static struct DirEntry * BuildDirList(const char *Path)
Definition: lastlog.c:144
defs.h
Declaration of the structures and functions.
IsTreeFileDirName
bool IsTreeFileDirName(const char *Name)
Definition: util.c:1257
DirEntry::Time
time_t Time
Definition: lastlog.c:33
DirEntry::Next
struct DirEntry * Next
Definition: lastlog.c:32
ngettext
#define ngettext(Msgid1, Msgid2, N)
Definition: gettext.h:75
IsTreeYearFileName
bool IsTreeYearFileName(const char *Name)
Definition: util.c:1350
debuga_more
void debuga_more(const char *msg,...)
Definition: util.c:631
debug
int debug
Definition: conf.h:489
DeleteDirList
static void DeleteDirList(struct DirEntry *List)
Definition: lastlog.c:37