#include "include/conf.h"
#include "include/defs.h"
-void mklastlog(const char *outdir)
+struct DirEntry
+{
+ struct DirEntry *Next;
+ time_t Time;
+ char *Name;
+};
+
+static void DeleteDirList(struct DirEntry *List)
+{
+ struct DirEntry *Next;
+
+ while (List)
+ {
+ Next=List->Next;
+ if (List->Name) free(List->Name);
+ free(List);
+ List=Next;
+ }
+}
+
+static struct DirEntry *AppendDirEntry(struct DirEntry *List,time_t CreationTime,const char *Name,int NameLen)
+{
+ struct DirEntry *entry;
+ struct DirEntry *prev;
+ struct DirEntry *ptr;
+
+ entry=malloc(sizeof(*entry));
+ if (!entry) {
+ debuga(_("Not enough memory to store a report to purge\n"));
+ DeleteDirList(List);
+ return(NULL);
+ }
+ entry->Name=malloc((NameLen+1)*sizeof(char));
+ if (!entry->Name) {
+ free(entry);
+ debuga(_("Not enough memory to store a report to purge\n"));
+ DeleteDirList(List);
+ return(NULL);
+ }
+ entry->Time=CreationTime;
+ strcpy(entry->Name,Name);
+
+ // store most recent file first
+ prev=NULL;
+ for (ptr=List ; ptr ; ptr=ptr->Next)
+ {
+ if (ptr->Time>CreationTime) break;
+ prev=ptr;
+ }
+ entry->Next=ptr;
+ if (prev)
+ prev->Next=entry;
+ else
+ List=entry;
+
+ return(List);
+}
+
+static struct DirEntry *BuildDirList(const char *Path)
{
- FILE *fp_in, *fp_ou;
DIR *dirp;
struct dirent *direntp;
- char buf[MAXLEN];
- char temp[MAXLEN];
- char warea[MAXLEN];
- char ftime[128];
- int ftot=0;
- time_t t;
- struct tm *local;
struct stat statb;
- int cstatus;
- struct getwordstruct gwarea;
-
- if(LastLog <= 0)
- return;
+ char warea[MAXLEN];
+ int name_pos;
+ int name_len;
+ struct DirEntry *List=NULL;
- if (snprintf(temp,sizeof(temp),"%s/lastlog1",tmp)>=sizeof(temp)) {
- debuga(_("File name too long: %s/lastlog1\n"),tmp);
- exit(EXIT_FAILURE);
- }
- if((fp_ou=fopen(temp,"w"))==NULL) {
- debuga(_("(lastlog) Cannot open temporary file %s: %s\n"),temp,strerror(errno));
+ name_pos=strlen(Path);
+ if (name_pos>=sizeof(warea)) {
+ debuga(_("The directory containing the old reports to purge is too long: %s\n"),Path);
exit(EXIT_FAILURE);
}
-
+ strcpy(warea,Path);
if ((dirp = opendir(outdir)) == NULL) {
debuga(_("Failed to open directory %s - %s\n"),outdir,strerror(errno));
exit(EXIT_FAILURE);
}
- while ((direntp = readdir( dirp )) != NULL ){
- if(strchr(direntp->d_name,'-') == 0)
- continue;
+ while ((direntp = readdir( dirp )) != NULL )
+ {
+ if (!IsTreeFileDirName(direntp->d_name)) continue;
- snprintf(warea,sizeof(warea),"%s%s",outdir,direntp->d_name);
+ 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);
+ exit(EXIT_FAILURE);
+ }
+ strcpy(warea+name_pos,direntp->d_name);
if (stat(warea,&statb) == -1) {
- debuga(_("Failed to get the creation time of %s\n"),warea);
+ debuga(_("Failed to get the last modification time of %s\n"),warea);
continue;
}
- t=statb.st_ctime;
- local = localtime(&t);
- strftime(ftime, sizeof(ftime), "%Y%m%d%H%M%S", local);
- fprintf(fp_ou,"%s\t%s\n",ftime,direntp->d_name);
- ftot++;
+ 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;
+ }
}
- closedir( dirp );
- if (fclose(fp_ou)==EOF) {
- debuga(_("Write error in %s: %s\n"),temp,strerror(errno));
- exit(EXIT_FAILURE);
- }
+ closedir(dirp);
+ return(List);
+}
+
+void mklastlog(const char *outdir)
+{
+ char warea[MAXLEN];
+ int name_pos;
+ int ftot=0;
+ struct DirEntry *List;
+ struct DirEntry *ptr;
+
+ if(LastLog <= 0)
+ return;
+
+ List=BuildDirList(outdir);
+ if (!List) return;
+
+ for (ptr=List ; ptr ; ptr=ptr->Next) ftot++;
+ if (debug)
+ debuga(ngettext("%d report directory found\n","%d report directories found\n",ftot),ftot);
if(ftot<=LastLog) {
+ DeleteDirList(List);
if (debug) {
debuga(ngettext("No old reports to delete as only %d report currently exists\n",
"No old reports to delete as only %d reports currently exist\n",ftot),ftot);
}
- if (!KeepTempLog && unlink(temp)) {
- debuga(_("Cannot delete \"%s\": %s\n"),temp,strerror(errno));
- exit(EXIT_FAILURE);
- }
return;
}
- if (snprintf(buf,sizeof(buf),"sort -n -t \"\t\" -k 1,1 -o \"%s/lastlog\" \"%s\"",tmp,temp)>=sizeof(buf)) {
- debuga(_("Cannot sort last reports list as the resulting command is too long\n"));
- exit(EXIT_FAILURE);
- }
- cstatus=system(buf);
- if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) {
- debuga(_("sort command return status %d\n"),WEXITSTATUS(cstatus));
- debuga(_("sort command: %s\n"),buf);
- exit(EXIT_FAILURE);
- }
-
- if (!KeepTempLog && unlink(temp)) {
- debuga(_("Cannot delete \"%s\": %s\n"),temp,strerror(errno));
- exit(EXIT_FAILURE);
- }
-
- if (debug)
- debuga(ngettext("%d report directory found\n","%d report directories found\n",ftot),ftot);
ftot-=LastLog;
if (debug)
debuga(ngettext("%d old report to delete\n","%d old reports to delete\n",ftot),ftot);
- snprintf(temp,sizeof(temp),"%s/lastlog",tmp);
- if((fp_in=fopen(temp,"r"))==NULL) {
- debuga(_("(lastlog) Cannot open temporary file %s: %s\n"),temp,strerror(errno));
+ name_pos=strlen(outdir);
+ if (name_pos>=sizeof(warea)) {
+ DeleteDirList(List);
+ debuga(_("The directory containing the old reports to purge is too long: %s\n"),outdir);
exit(EXIT_FAILURE);
}
-
- while(ftot>0 && fgets(buf,sizeof(buf),fp_in)!=NULL) {
- fixendofline(buf);
- getword_start(&gwarea,buf);
- if (getword(warea,sizeof(warea),&gwarea,'\t')<0) {
- debuga(_("Maybe you have a broken record or garbage in your %s file\n"),temp);
- exit(EXIT_FAILURE);
- }
-
+ strcpy(warea,outdir);
+ for (ptr=List ; ptr && ftot>0 ; ptr=ptr->Next)
+ {
if(debug)
- debuga(_("Removing old report file %s\n"),gwarea.current);
- if (snprintf(temp,sizeof(temp),"%s%s",outdir,gwarea.current)>=sizeof(temp)) {
- debuga(_("Directory name too long: %s%s\n"),outdir,gwarea.current);
+ debuga(_("Removing old report file %s\n"),ptr->Name);
+ if (name_pos+strlen(ptr->Name)+1>=sizeof(warea)) {
+ DeleteDirList(List);
+ debuga(_("Directory name too long: %s%s\n"),outdir,ptr->Name);
exit(EXIT_FAILURE);
}
- unlinkdir(temp,0);
+ strcpy(warea+name_pos,ptr->Name);
+ //unlinkdir(warea,0);
ftot--;
}
- fclose(fp_in);
- if (!KeepTempLog) {
- snprintf(temp,sizeof(temp),"%s/lastlog",tmp);
- if (unlink(temp) == -1)
- debuga(_("Cannot delete \"%s\": %s\n"),temp,strerror(errno));
- }
-
+ DeleteDirList(List);
return;
}
return;
}
+/*!
+ * Check if the proposed file name conforms to the directory structure layed out
+ * as a file tree. It is used to check if the file name enumerated while scanning
+ * a directory content may have been created by sarg running with IndexTree set to
+ * INDEX_TREE_FILE.
+ */
+bool IsTreeFileDirName(const char *Name)
+{
+ char DateFormat;
+ int i;
+
+ // start year (date format u) or start day (date format e)
+ if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false);
+
+ if (isdigit(Name[2]) && isdigit(Name[3]))
+ {
+ // date format is either u or w
+ if (Name[4]=='.')
+ {
+ // date format is w
+ if (!isdigit(Name[5]) || !isdigit(Name[6])) return(false);
+ return(true);//date format w is confirmed
+ }
+
+ // date format is u
+ Name+=4;
+
+ // start month
+ if (!isalpha(Name[0]) || !isalpha(Name[1]) || !isalpha(Name[2])) return(false);
+ for (i=11 ; i>=0 && memcmp(mtab1[i],Name,3) ; i--);
+ if (i<0) return(false);
+ Name+=3;
+
+ // start day
+ if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false);
+ Name+=2;
+
+ DateFormat='u';
+ }
+ else if (isalpha(Name[2]) && isalpha(Name[3]) && isalpha(Name[4]))
+ {
+ // date format is e
+ Name+=2;
+
+ // start month
+ if (!isalpha(Name[0]) || !isalpha(Name[1]) || !isalpha(Name[2])) return(false);
+ for (i=11 ; i>=0 && memcmp(mtab1[i],Name,3) ; i--);
+ if (i<0) return(false);
+ Name+=3;
+
+ // start day
+ if (!isdigit(Name[0]) || !isdigit(Name[1]) || !isdigit(Name[2]) || !isdigit(Name[3])) return(false);
+ Name+=4;
+
+ DateFormat='e';
+ }
+ else
+ return(false);
+
+ if (Name[0]!='-') return(false);
+ Name++;
+
+ if (DateFormat=='u')
+ {
+ if (!isdigit(Name[0]) || !isdigit(Name[1]) || !isdigit(Name[2]) || !isdigit(Name[3])) return(false);
+ Name+=4;
+
+ if (!isalpha(Name[0]) || !isalpha(Name[1]) || !isalpha(Name[2])) return(false);
+ for (i=11 ; i>=0 && memcmp(mtab1[i],Name,3) ; i--);
+ if (i<0) return(false);
+ Name+=3;
+
+ if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false);
+ Name+=2;
+ }
+ else //DateFormat=='e'
+ {
+ if (!isdigit(Name[0]) || !isdigit(Name[1])) return(false);
+ Name+=2;
+
+ if (!isalpha(Name[0]) || !isalpha(Name[1]) || !isalpha(Name[2])) return(false);
+ for (i=11 ; i>=0 && memcmp(mtab1[i],Name,3) ; i--);
+ if (i<0) return(false);
+ Name+=3;
+
+ if (!isdigit(Name[0]) || !isdigit(Name[1]) || !isdigit(Name[2]) || !isdigit(Name[3])) return(false);
+ Name+=4;
+ }
+ /*
+ * The directory may contains additional characters such as a counter
+ * if a previous report is never overwritten.
+ */
+ return(true);
+}
+
int vrfydir(const struct periodstruct *per1, const char *addr, const char *site, const char *us, const char *form)
{
FILE *fp_ou;