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;
}
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);
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;
+ }
}
}
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];
}
strcpy(warea+name_pos,ptr->Name);
unlinkdir(warea,0);
+ DeleteEmptyDirs(warea,sizeof(warea),name_pos);
ftot--;
}
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);
}