X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=splitlog.c;h=0816e03fdf381ebf13eca0842b9ee6241c115f53;hb=82aba1f76795d95bed1c1b948e2e521168e97fc9;hp=69c015365512185c6fa51cb3e07db23862472cd7;hpb=fbd133bb130a104b731b827226b67b19fa99d272;p=thirdparty%2Fsarg.git diff --git a/splitlog.c b/splitlog.c index 69c0153..0816e03 100644 --- a/splitlog.c +++ b/splitlog.c @@ -1,6 +1,6 @@ /* * SARG Squid Analysis Report Generator http://sarg.sourceforge.net - * 1998, 2011 + * 1998, 2015 * * SARG donations: * please look at http://sarg.sourceforge.net/donations.php @@ -27,35 +27,73 @@ #include "include/conf.h" #include "include/defs.h" -void splitlog(const char *arq, char *df, int dfrom, int duntil, int convert) +/* +Extract a date range from a squid log file and write it into a separate file. + +It can optionally convert the date in human readable format. + +The output can be split by day into separate files. + +\param arq The squid log file to split. +\param df The date format if the date is to be converted in human readable form. Only the first +character is taken into account. It can be 'e' for European date format or anything else for +US date format. +\param dfrom The first date to output in the form (Year*10000+Month*100+Day). +\param duntil The last date to output in the form (Year*10000+Month*100+Day). +\param convert \c True if the date must be converted into human readable form. +\param splitprefix If not empty, the output file is written in separate files (one for each day) and +the files are named after the day they contain prefixed with the string contained in this variable. +*/ +void splitlog(const char *arq, char df, int dfrom, int duntil, int convert, const char *splitprefix) { - FILE *fp_in; + FileObject *fp_in; + FILE *fp_ou=NULL; char *buf; char data[30]; char dia[11]; + char output_file[MAXLEN]; time_t tt; + time_t min_tt; + time_t max_tt=0; int idata=0; + int autosplit=0; + int output_prefix_len=0; + int prev_year=0, prev_month=0, prev_day=0; struct tm *t; struct getwordstruct gwarea; longline line; + if (splitprefix[0]!='\0') { + // '/' + '-YYYY-mm-dd' + '\0' == 13 + output_prefix_len=snprintf(output_file,sizeof(output_file)-12,"%s%s",outdir,splitprefix); + if (output_prefix_len>=sizeof(output_file)-12) { + debuga(__FILE__,__LINE__,_("Path too long: ")); + debuga_more("%s%s-YYYY-mm-dd\n",outdir,splitprefix); + exit(EXIT_FAILURE); + } + autosplit=1; + } else { + fp_ou=stdout; + } + if(arq[0] == '\0') arq="/var/log/squid/access.log"; - if((fp_in=MY_FOPEN(arq,"r"))==NULL) { - debuga(_("(splitlog) Cannot open log file %s - %s\n"),arq,strerror(errno)); + if((fp_in=FileObject_Open(arq))==NULL) { + debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),arq,FileObject_GetLastOpenError()); exit(EXIT_FAILURE); } if ((line=longline_create())==NULL) { - debuga(_("Not enough memory to read the log file %s\n"),arq); + debuga(__FILE__,__LINE__,_("Not enough memory to read file \"%s\"\n"),arq); exit(EXIT_FAILURE); } + time(&min_tt); while((buf=longline_read(fp_in,line))!=NULL) { getword_start(&gwarea,buf); if (getword(data,sizeof(data),&gwarea,' ')<0) { - debuga(_("Invalid date found in file %s\n"),arq); + debuga(__FILE__,__LINE__,_("Invalid date in file \"%s\"\n"),arq); exit(EXIT_FAILURE); } tt=atoi(data); @@ -67,20 +105,49 @@ void splitlog(const char *arq, char *df, int dfrom, int duntil, int convert) continue; } + if (autosplit && (prev_year!=t->tm_year || prev_month!=t->tm_mon || prev_day!=t->tm_mday)) { + prev_year=t->tm_year; + prev_month=t->tm_mon; + prev_day=t->tm_mday; + if (fp_ou && fclose(fp_ou)==EOF) { + debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),output_file,strerror(errno)); + exit(EXIT_FAILURE); + } + strftime(output_file+output_prefix_len, sizeof(output_file)-output_prefix_len, "-%Y-%m-%d", t); + /* + The line must be added to a file we have already created. The file must be created if the date + is seen for the first time. The idea is to create the files from scratch if the split is started + a second time. + */ + if ((fp_ou=MY_FOPEN(output_file,(tt>=min_tt && tt<=max_tt) ? "a" : "w"))==NULL) { + debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),output_file,strerror(errno)); + exit(EXIT_FAILURE); + } + if (ttmax_tt) max_tt=tt; + } + if(!convert) { - printf("%s %s\n",data,gwarea.current); + fprintf(fp_ou,"%s %s\n",data,gwarea.current); } else { - if(df[0]=='e') + if (df=='e') strftime(dia, sizeof(dia), "%d/%m/%Y", t); else strftime(dia, sizeof(dia), "%m/%d/%Y", t); - printf("%s %02d:%02d:%02d %s\n",dia,t->tm_hour,t->tm_min,t->tm_sec,gwarea.current); + fprintf(fp_ou,"%s %02d:%02d:%02d %s\n",dia,t->tm_hour,t->tm_min,t->tm_sec,gwarea.current); } } longline_destroy(&line); - if (fclose(fp_in)==EOF) { - debuga(_("Failed to close file %s - %s\n"),arq,strerror(errno)); + if (FileObject_Close(fp_in)) { + debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),arq,FileObject_GetLastCloseError()); + exit(EXIT_FAILURE); + } + if (autosplit && fp_ou) { + if (fclose(fp_ou)==EOF) { + debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),output_file,strerror(errno)); + exit(EXIT_FAILURE); + } } }