X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=totday.c;h=9d80b8ba74b7bd67f8da470273329594f045eb41;hb=82aba1f76795d95bed1c1b948e2e521168e97fc9;hp=fb1b07968d4680997c58656ac428a701121c915c;hpb=456d78a5fd76464803abad4026237433a8937b44;p=thirdparty%2Fsarg.git diff --git a/totday.c b/totday.c index fb1b079..9d80b8b 100644 --- a/totday.c +++ b/totday.c @@ -1,10 +1,11 @@ /* - * AUTHOR: Pedro Lineu Orso pedro.orso@gmail.com - * 1998, 2008 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net + * 1998, 2015 * * SARG donations: * please look at http://sarg.sourceforge.net/donations.php + * Support: + * http://sourceforge.net/projects/sarg/forums/forum/363374 * --------------------------------------------------------------------- * * This program is free software; you can redistribute it and/or modify @@ -24,112 +25,185 @@ */ #include "include/conf.h" +#include "include/defs.h" -void day_totalize(const char *tmp, char *user, int indexonly) +//! The daily statistics for one user. +struct DayStruct { + int ndaylist; + int maxindex; + int daylist[MAX_DATETIME_DAYS]; + long long int bytes[MAX_DATETIME_DAYS*24]; + long long int elap[MAX_DATETIME_DAYS*24]; +}; + +/*! +Prepare the object to store the daily statistics of one user. + +\return The object to pass to other functions in this module. +The object must be freed with a call to day_cleanup(). +*/ +DayObject day_prepare(void) +{ + DayObject ddata; + + ddata=(DayObject)malloc(sizeof(*ddata)); + if (!ddata) + { + debuga(__FILE__,__LINE__,_("Not enough memory to store the daily statistics\n")); + exit(EXIT_FAILURE); + } + + return(ddata); +} - FILE *fp_in, *fp_ou; - - char data[20]; - char hora[20]; - char min[20]; - char elap[20]; - char odata[20]; - char ohora[20]; - char oelap[20]; - char hm[20]; - char ohm[20]; - char csort[255]; - char wdirname[MAXLEN]; - char sortout[MAXLEN]; - char arqout[MAXLEN]; - int regs=0; - long long int telap=0; - long long int tused=0; - int cstatus; - - if(indexonly) return; - if(strstr(ReportType,"users_sites") == 0) return; - - sprintf(wdirname,"%s/%s.htmp",tmp,user); - sprintf(arqout,"%s/%s.day",tmp,user); - sprintf(sortout,"%s/%s.sort",tmp,user); - - sprintf(csort,"sort -k 1,1 -k 2,2 -o '%s' '%s'",sortout,wdirname); - cstatus=system(csort); - if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus)) { - fprintf(stderr, "SARG: sort command return status %d\n",WEXITSTATUS(cstatus)); - fprintf(stderr, "SARG: sort command: %s\n",csort); - exit(1); - } - if((fp_in=fopen(sortout,"r"))==NULL) { - fprintf(stderr, "SARG: (totday) %s: %s\n",text[8],sortout); - fprintf(stderr, "SARG: sort command: %s\n",csort); - exit(1); - } - - unlink(wdirname); - - if((fp_ou=fopen(arqout,"w"))==NULL) { - fprintf(stderr, "SARG: (totday) %s: %s\n",text[8],arqout); - exit(1); - } - - while(fgets(buf,sizeof(buf),fp_in)!=NULL) { - if(strstr(buf,"\n") != 0) - buf[strlen(buf)-1]='\0'; - - if (getword(data,sizeof(data),buf,' ')<0 || getword(hora,sizeof(hora),buf,':')<0 || - getword(min,sizeof(min),buf,':')<0 || getword(elap,sizeof(elap),buf,' ')<0 || - getword(elap,sizeof(elap),buf,0)<0) { - printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",sortout); - exit(1); - } - sprintf(hm,"%s%s",hora,min); - - if(!regs) { - strcpy(odata,data); - strcpy(ohora,hora); - strcpy(oelap,elap); - strcpy(ohm,hm); - regs++; - } - - if(strcmp(hora,ohora) != 0 || strcmp(data,odata) != 0) { - if(tused > telap) - tused=telap; - - my_lltoa(telap,val1,15); - sprintf(buf,"%s %s %s\n",odata,ohora,val1); - fputs(buf, fp_ou); - strcpy(odata,data); - strcpy(ohora,hora); - strcpy(ohm,hm); - telap=0; - tused=0; - } - - if(strcmp(ohm,hm) != 0) { - tused+=60000; - strcpy(ohm,hm); - } - - telap+=my_atoll(elap); - - } - - if(tused > telap) - tused=telap; - - my_lltoa(telap,val1,15); - sprintf(buf,"%s %s %s\n",data,hora,val1); - fputs(buf, fp_ou); - - fclose(fp_in); - fclose(fp_ou); - - unlink(sortout); - - return; +/*! +Free the memory allocated by day_prepare(). + +\param ddata The object returned by day_prepare(). +*/ +void day_cleanup(DayObject ddata) +{ + if (ddata) free(ddata); +} +/*! +Prepare the object for a new user. + +\param ddata The object created by day_prepare(). +*/ +void day_newuser(DayObject ddata) +{ + if (ddata) + { + ddata->ndaylist=0; + ddata->maxindex=0; + memset(ddata->bytes,0,sizeof(ddata->bytes)); + memset(ddata->elap,0,sizeof(ddata->elap)); + } +} + +/*! +Store one data point in the statistics. + +\param ddata The object to store the statistics. +\param date The date of the data point formated as day/month/year. +\param time The time of the data point. +\param elap The time spent processing the user's request on the proxy. +\param bytes The number of bytes transfered by the user. +*/ +void day_addpoint(DayObject ddata,const char *date, const char *time, long long int elap, long long int bytes) +{ + int hour; + int day,month,year; + int daynum; + int dayidx; + int i; + + if (!ddata) return; + if (sscanf(date,"%d/%d/%d",&day,&month,&year)!=3) { + debuga(__FILE__,__LINE__,_("Invalid date \"%s\" for the hourly statistics\n"),date); + exit(EXIT_FAILURE); + } + if (day<1 || day>31 || month<1 || month>12 || year>9999) { + debuga(__FILE__,__LINE__,_("Invalid date component in \"%s\" for the hourly statistics\n"),date); + exit(EXIT_FAILURE); + } + hour=atoi(time); + if (hour<0 || hour>=24) { + debuga(__FILE__,__LINE__,_("Invalid hour %d for the hourly statistics\n"),hour); + exit(EXIT_FAILURE); + } + daynum=(year*10000)+(month*100)+day; + for (dayidx=ddata->ndaylist-1 ; dayidx>=0 && daynum!=ddata->daylist[dayidx] ; dayidx--); + if (dayidx<0) { + dayidx=ddata->ndaylist++; + if (dayidx>=sizeof(ddata->daylist)/sizeof(*ddata->daylist)) { + debuga(__FILE__,__LINE__,_("Too many different dates for the hourly statistics\n")); + exit(EXIT_FAILURE); + } + ddata->daylist[dayidx]=daynum; + } + i=dayidx*24+hour; + if (i>=ddata->maxindex) ddata->maxindex=i+1; + ddata->bytes[i]+=bytes; + ddata->elap[i]+=elap; } + +/*! +Store the dayly statistics in the file. + +\param ddata The object containing the statistics. +\param tmp The temporary directory to store the file into. +\param uinfo The user's data. +*/ +void day_totalize(DayObject ddata,const char *tmp, const struct userinfostruct *uinfo) +{ + FILE *fp_ou; + int hour; + int day,month,year; + int i; + int daynum; + int dayidx; + char arqout[2048]; + + if (datetimeby==0) return; + if (!ddata) return; + + if (snprintf(arqout,sizeof(arqout),"%s/%s.day",tmp,uinfo->filename)>=sizeof(arqout)) { + debuga(__FILE__,__LINE__,_("Path too long: ")); + debuga_more("%s/%s%s\n",tmp,uinfo->filename,".day"); + exit(EXIT_FAILURE); + } + + if((fp_ou=fopen(arqout,"w"))==NULL) { + debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),arqout,strerror(errno)); + exit(EXIT_FAILURE); + } + + for (i=0 ; imaxindex ; i++) { + if (ddata->bytes[i]==0 && ddata->elap[i]==0) continue; + dayidx=i/24; + if (dayidx>=sizeof(ddata->daylist)/sizeof(*ddata->daylist)) { + debuga(__FILE__,__LINE__,_("Invalid day index found in the hourly statistics\n")); + exit(EXIT_FAILURE); + } + hour=i%24; + daynum=ddata->daylist[dayidx]; + day=daynum%100; + month=(daynum/100)%100; + year=daynum/10000; + fprintf(fp_ou,"%d/%d/%d\t%d",day,month,year,hour); + if ((datetimeby & DATETIME_BYTE)!=0) fprintf(fp_ou,"\t%"PRIu64"",(uint64_t)ddata->bytes[i]); + if ((datetimeby & DATETIME_ELAP)!=0) fprintf(fp_ou,"\t%"PRIu64"",(uint64_t)ddata->elap[i]); + fputs("\n",fp_ou); + } + + if (fclose(fp_ou)==EOF) { + debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),arqout,strerror(errno)); + exit(EXIT_FAILURE); + } + return; +} + +/*! +Delete the temporary file generated by day_totalize(). + +\param uinfo The user whose daily statistics are to be deleted. +*/ +void day_deletefile(const struct userinfostruct *uinfo) +{ + char arqout[2048]; + + if (KeepTempLog) return; + + if (snprintf(arqout,sizeof(arqout),"%s/%s.day",tmp,uinfo->filename)>=sizeof(arqout)) { + debuga(__FILE__,__LINE__,_("Path too long: ")); + debuga_more("%s/%s%s\n",tmp,uinfo->filename,".day"); + exit(EXIT_FAILURE); + } + + if (unlink(arqout)) + debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),arqout,strerror(errno)); +} +