]> git.ipfire.org Git - thirdparty/sarg.git/commitdiff
Delete old reports when index_tree is set to "date"
authorFrederic Marchal <fmarchal@users.sourceforge.net>
Tue, 30 Sep 2014 19:09:39 +0000 (21:09 +0200)
committerFrederic Marchal <fmarchal@users.sourceforge.net>
Tue, 30 Sep 2014 19:09:39 +0000 (21:09 +0200)
Sarg goes to great length to make sure no unrelated directories are
deleted.

A list of every report directory is build. It is sorted in ascending order
on the last modification time. If too many directories are present, the
oldest ones are deleted including the possibly remaining empty parent
directory.

The index.html file is not rebuild to account for the deleted reports yet.

include/defs.h
lastlog.c
util.c

index 60e5adbb49a83c7eee24ce7e92e174671617eb25..720eb9b1662bcd1925f9520eca01ca9ec6a51502 100755 (executable)
@@ -391,6 +391,9 @@ int month2num(const char *month);
 int builddia(int day, int month, int year);
 int compare_date(struct tm *date1,struct tm *date2);
 bool IsTreeFileDirName(const char *Name);
+bool IsTreeYearFileName(const char *Name);
+bool IsTreeMonthFileName(const char *Name);
+bool IsTreeDayFileName(const char *Name);
 int vrfydir(const struct periodstruct *per1, const char *addr, const char *site, const char *us, const char *form);
 int getperiod_fromsarglog(const char *arqtt,struct periodstruct *period);
 void getperiod_fromrange(struct periodstruct *period,int dfrom,int duntil);
index 0b58b5d23f31a948b03fb08022e8108deab3e74e..43276f4e31707476ec2d3fa6bdbfb9ebad12ab45 100644 (file)
--- a/lastlog.c
+++ b/lastlog.c
@@ -85,6 +85,62 @@ static struct DirEntry *AppendDirEntry(struct DirEntry *List,time_t CreationTime
        return(List);
 }
 
+static struct DirEntry *BuildDirDateList(struct DirEntry *List,char *Path,int PathSize,int RootPos,int Length,int Level)
+{
+       DIR *dirp;
+       struct dirent *direntp;
+       struct stat statb;
+       int name_len;
+
+       if ((dirp = opendir(Path)) == NULL) {
+               debuga(_("Failed to open directory %s - %s\n"),Path,strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       while ((direntp = readdir( dirp )) != NULL )
+       {
+               name_len=strlen(direntp->d_name);
+               if (RootPos+name_len+1>=PathSize) {
+                       debuga(_("Directory entry too long to purge the old reports: %s%s\n"),Path,direntp->d_name);
+                       exit(EXIT_FAILURE);
+               }
+               strcpy(Path+Length,direntp->d_name);
+               if (stat(Path,&statb) == -1) {
+                       debuga(_("Failed to get the last modification time of %s\n"),Path);
+                       continue;
+               }
+               if (!S_ISDIR(statb.st_mode)) continue;
+               if (Level==0)
+               {
+                       if (IsTreeMonthFileName(direntp->d_name))
+                       {
+                               Path[Length+name_len]='/';
+                               Path[Length+name_len+1]='\0';
+                               List=BuildDirDateList(List,Path,PathSize,RootPos,Length+name_len+1,1);
+                               if (!List)
+                               {
+                                       debuga(_("Old reports deletion not undertaken due to previous error\n"));
+                                       break;
+                               }
+                       }
+               }
+               else if (Level==1)
+               {
+                       if (IsTreeDayFileName(direntp->d_name))
+                       {
+                               List=AppendDirEntry(List,statb.st_mtime,Path+RootPos,Length-RootPos+name_len);
+                               if (!List)
+                               {
+                                       debuga(_("Old reports deletion not undertaken due to previous error\n"));
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       closedir(dirp);
+       return(List);
+}
+
 static struct DirEntry *BuildDirList(const char *Path)
 {
        DIR *dirp;
@@ -107,8 +163,6 @@ static struct DirEntry *BuildDirList(const char *Path)
        }
        while ((direntp = readdir( dirp )) != NULL )
        {
-               if (!IsTreeFileDirName(direntp->d_name)) continue;
-
                name_len=strlen(direntp->d_name);
                if (name_pos+name_len+1>=sizeof(warea)) {
                        debuga(_("Directory entry too long to purge the old reports: %s%s\n"),Path,direntp->d_name);
@@ -119,11 +173,26 @@ static struct DirEntry *BuildDirList(const char *Path)
                        debuga(_("Failed to get the last modification time of %s\n"),warea);
                        continue;
                }
-               List=AppendDirEntry(List,statb.st_mtime,direntp->d_name,name_len);
-               if (!List)
+               if (!S_ISDIR(statb.st_mode)) continue;
+               if (IsTreeFileDirName(direntp->d_name))
                {
-                       debuga(_("Old reports deletion not undertaken due to previous error\n"));
-                       break;
+                       List=AppendDirEntry(List,statb.st_mtime,direntp->d_name,name_len);
+                       if (!List)
+                       {
+                               debuga(_("Old reports deletion not undertaken due to previous error\n"));
+                               break;
+                       }
+               }
+               else if (IsTreeYearFileName(direntp->d_name))
+               {
+                       warea[name_pos+name_len]='/';
+                       warea[name_pos+name_len+1]='\0';
+                       List=BuildDirDateList(List,warea,sizeof(warea),name_pos,name_pos+name_len+1,0);
+                       if (!List)
+                       {
+                               debuga(_("Old reports deletion not undertaken due to previous error\n"));
+                               break;
+                       }
                }
        }
 
@@ -131,6 +200,60 @@ static struct DirEntry *BuildDirList(const char *Path)
        return(List);
 }
 
+static void DeleteEmptyDirs(char *Path,int PathSize,int BasePos)
+{
+       char *Dir;
+       DIR *dirp;
+       struct dirent *direntp;
+       bool index;
+
+       while ((Dir=strrchr(Path,'/'))!=NULL)
+       {
+               if (Dir-Path<=BasePos) break;
+               *Dir='\0';
+               if ((dirp = opendir(Path)) == NULL) {
+                       debuga(_("Failed to open directory %s - %s\n"),Path,strerror(errno));
+                       return;
+               }
+               index=false;
+               while ((direntp = readdir( dirp )) != NULL )
+               {
+                       if (direntp->d_name[0]=='.' && (direntp->d_name[1]=='\0' || (direntp->d_name[1]=='.' && direntp->d_name[2]=='\0'))) continue;
+                       if (!strcmp(direntp->d_name,INDEX_HTML_FILE))
+                       {
+                               index=true;
+                               continue;
+                       }
+                       break;
+               }
+               closedir(dirp);
+               if (direntp!=NULL) {
+                       // at least one file exists in the directory, don't delete the directory
+                       break;
+               }
+               if (debug)
+                       debuga(_("Deleting empty directory %s\n"),Path);
+               if (index) {
+                       if (strlen(Path)+strlen(INDEX_HTML_FILE)+2>=PathSize) {
+                               debuga(_("Buffer to small to delete index file %s/%s"),Path,INDEX_HTML_FILE);
+                               exit(EXIT_FAILURE);
+                       }
+                       strcat(Path,"/"INDEX_HTML_FILE);
+                       if (unlink(Path)==-1) {
+                               // TRANSLATORS: The %s at the end is the system error message describing the reason for the failure.
+                               debuga(_("Failed to delete index file \"%s\" in the empty report directory: %s\n"),Path,strerror(errno));
+                               exit(EXIT_FAILURE);
+                       }
+                       *Dir='\0';
+               }
+               if (rmdir(Path)) {
+                       debuga(_("Cannot delete \"%s\": %s\n"),Path,strerror(errno));
+                       exit(EXIT_FAILURE);
+               }
+       }
+       //! \todo Rebuild the surviving index file
+}
+
 void mklastlog(const char *outdir)
 {
        char warea[MAXLEN];
@@ -180,6 +303,7 @@ void mklastlog(const char *outdir)
                }
                strcpy(warea+name_pos,ptr->Name);
                unlinkdir(warea,0);
+               DeleteEmptyDirs(warea,sizeof(warea),name_pos);
                ftot--;
        }
 
diff --git a/util.c b/util.c
index e10a16943e3db2d9c4abfc26ddc0ed37ab767afe..cf44007b38865a36732a637d9347fedd18453303 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1212,8 +1212,75 @@ bool IsTreeFileDirName(const char *Name)
                Name+=4;
        }
        /*
-        * The directory may contains additional characters such as a counter
-        * if a previous report is never overwritten.
+        * The directory name may contains additional characters such as a counter if
+        * a previous report is never overwritten.
+        */
+       return(true);
+}
+
+/*!
+ * Check if the proposed file name can be the year part of a report tree build with
+ * IndexTree set to INDEX_TREE_DATE.
+ */
+bool IsTreeYearFileName(const char *Name)
+{
+       if (!isdigit(Name[0]) || !isdigit(Name[1]) || !isdigit(Name[2]) || !isdigit(Name[3])) return(false);
+       Name+=4;
+       if (Name[0]=='-')
+       {
+               Name++;
+               if (!isdigit(Name[0]) || !isdigit(Name[1]) || !isdigit(Name[2]) || !isdigit(Name[3])) return(false);
+               Name+=4;
+       }
+       if (Name[0]) return(false);
+       return(true);
+}
+
+/*!
+ * Check if the proposed file name can be the month part of a report tree build with
+ * IndexTree set to INDEX_TREE_DATE.
+ */
+bool IsTreeMonthFileName(const char *Name)
+{
+       int m;
+
+       if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false);
+       m=(Name[0]-'0')*10+(Name[1]-'0');
+       if (m<1 || m>12) return(false);
+       Name+=2;
+       if (Name[0]=='-')
+       {
+               Name++;
+               if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false);
+               m=(Name[0]-'0')*10+(Name[1]-'0');
+               if (m<1 || m>12) return(false);
+               Name+=2;
+       }
+       if (Name[0]) return(false);
+       return(true);
+}
+
+/*!
+ * Check if the proposed file name can be the day part of a report tree build with
+ * IndexTree set to INDEX_TREE_DATE.
+ */
+bool IsTreeDayFileName(const char *Name)
+{
+       int d;
+
+       if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false);
+       d=(Name[0]-'0')*10+(Name[1]-'0');
+       if (d<1 || d>31) return(false);
+       if (Name[2]=='-')
+       {
+               Name+=3;
+               if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false);
+               d=(Name[0]-'0')*10+(Name[1]-'0');
+               if (d<1 || d>31) return(false);
+       }
+       /*
+        * The directory name may contains additional characters such as a counter if
+        * a previous report is never overwritten.
         */
        return(true);
 }