X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=splitlog.c;h=c8c9fa2924225091090d52bf569d5c3017116e57;hb=ffc9b006b8358644c054c5e4c2929791efec7475;hp=155c830be543cb5ba8ebe3e8523725a89a04fbc5;hpb=a96e796dac0ab1c115af25f6c26cc76851c233e2;p=thirdparty%2Fsarg.git diff --git a/splitlog.c b/splitlog.c index 155c830..c8c9fa2 100644 --- a/splitlog.c +++ b/splitlog.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 @@ -26,55 +27,127 @@ #include "include/conf.h" #include "include/defs.h" -void splitlog(const char *arq, char *df, int dfrom, int duntil, char *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; + 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; + } - FILE *fp_in; - char buf[MAXLEN]; - char data[30]; - char dia[11]; - char hora[9]; - char wdata[20]; - time_t tt; - int idata=0; - struct tm *t; + if(arq[0] == '\0') + arq="/var/log/squid/access.log"; - if(arq[0] == '\0') - arq="/var/log/squid/access.log"; + if((fp_in=MY_FOPEN(arq,"r"))==NULL) { + debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),arq,strerror(errno)); + exit(EXIT_FAILURE); + } - if((fp_in=MY_FOPEN(arq,"r"))==NULL) { - fprintf(stderr, "SARG: (splitlog) %s: %s\n",text[8],arq); - exit(1); - } + if ((line=longline_create())==NULL) { + debuga(__FILE__,__LINE__,_("Not enough memory to read file \"%s\"\n"),arq); + exit(EXIT_FAILURE); + } + time(&min_tt); - while(fgets(buf,sizeof(buf),fp_in)!=NULL) { - if (getword(data,sizeof(data),buf,' ')<0) { - printf("SARG: Maybe you have a broken record or garbage in your %s file.\n",arq); - exit(1); - } - tt=atoi(data); - t=localtime(&tt); + while((buf=longline_read(fp_in,line))!=NULL) { + getword_start(&gwarea,buf); + if (getword(data,sizeof(data),&gwarea,' ')<0) { + debuga(__FILE__,__LINE__,_("Invalid date in file \"%s\"\n"),arq); + exit(EXIT_FAILURE); + } + tt=atoi(data); + t=localtime(&tt); - if(dfrom) { - strftime(wdata, 127, "%Y%m%d", t); - idata=atoi(wdata); - if(idata < dfrom || idata > duntil) - continue; - } + if(dfrom) { + idata=(t->tm_year+1900)*10000+(t->tm_mon+1)*100+t->tm_mday; + if(idata < dfrom || idata > duntil) + continue; + } - if(strcmp(convert,"onvert") != 0) { - printf("%s %s",data,buf); - 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(strncmp(df,"e",1) == 0) - strftime(dia, 127, "%d/%m/%Y", t); - else - strftime(dia, 127, "%m/%d/%Y", t); + if(!convert) { + fprintf(fp_ou,"%s %s\n",data,gwarea.current); + } else { + if (df=='e') + strftime(dia, sizeof(dia), "%d/%m/%Y", t); + else + strftime(dia, sizeof(dia), "%m/%d/%Y", t); - sprintf(hora,"%02d:%02d:%02d",t->tm_hour,t->tm_min,t->tm_sec); - printf("%s %s %s",dia,hora,buf); - } + fprintf(fp_ou,"%s %02d:%02d:%02d %s\n",dia,t->tm_hour,t->tm_min,t->tm_sec,gwarea.current); + } + } - fclose(fp_in); + longline_destroy(&line); + if (fclose(fp_in)==EOF) { + debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),arq,strerror(errno)); + 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); + } + } }