X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fsarg.git;a=blobdiff_plain;f=util.c;h=aba23b191b769db4af96cb708361bda67c3d6bdb;hp=6ff809bb7f8309556a7e19454650f200fc30598b;hb=HEAD;hpb=f72b484ad4c51d08e4d950ae2faa275869ac45cb diff --git a/util.c b/util.c index 6ff809b..aba23b1 100644 --- a/util.c +++ b/util.c @@ -1,6 +1,6 @@ /* * SARG Squid Analysis Report Generator http://sarg.sourceforge.net - * 1998, 2013 + * 1998, 2015 * * SARG donations: * please look at http://sarg.sourceforge.net/donations.php @@ -30,6 +30,11 @@ #include "include/conf.h" #include "include/defs.h" +#if defined(__MINGW32__) && defined(HAVE_DIRECT_H) +#define NO_OLDNAMES 1 +#include +#endif + #if defined(HAVE_BACKTRACE) #define USE_GETWORD_BACKTRACE 1 #else @@ -41,6 +46,11 @@ static char mtab1[12][4]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep", //! The list of the HTTP codes to exclude from the report. static char *excludecode=NULL; +//! Directory where the images are stored. +char ImageDir[MAXLEN]=IMAGEDIR; + +extern char *CurrentLocale; + #if USE_GETWORD_BACKTRACE static void getword_backtrace(void) { @@ -52,7 +62,7 @@ static void getword_backtrace(void) if (n<=0) return; calls=backtrace_symbols(buffer,n); if (calls) { - debuga(_("getword backtrace:\n")); + debuga(__FILE__,__LINE__,_("getword backtrace:\n")); for (i=0 ; imodified) { - debuga(_("Cannot parse again the line as it was modified\n")); + debuga(__FILE__,__LINE__,_("Cannot parse again the line as it was modified\n")); exit(EXIT_FAILURE); } gwarea->current=gwarea->beginning; @@ -83,11 +93,14 @@ int getword(char *word, int limit, struct getwordstruct *gwarea, char stop) for(x=0;((gwarea->current[x]) && (gwarea->current[x] != stop ));x++) { if(x>=limit) { - debuga(_("End of word not found in getword after %d bytes.\n"),x); - debuga(_("Line=\"%s\"\n"),gwarea->beginning); - debuga(_("Record=\"%s\"\n"),gwarea->current); - debuga(_("searching for \'x%x\'\n"),stop); - //debuga(_("Maybe you have a broken record or garbage in your access.log file.\n")); + /* + TRANSLATORS: The %s is the name of the function reporting the + error message. + */ + debuga(__FILE__,__LINE__,_("End of word not found in %s after %d bytes.\n"),__func__,x); + debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning); + debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current); + debuga(__FILE__,__LINE__,_("searching for \'x%x\'\n"),stop); word[(limit>0) ? limit-1 : 0]='\0'; #if USE_GETWORD_BACKTRACE getword_backtrace(); @@ -124,11 +137,10 @@ int getword_multisep(char *word, int limit, struct getwordstruct *gwarea, char s for(x=0;((gwarea->current[x]) && (gwarea->current[x] != stop ));x++) { if(x>=limit) { - debuga(_("End of word not found in getword_multisep after %d bytes.\n"),x); - debuga(_("Line=\"%s\"\n"),gwarea->beginning); - debuga(_("Record=\"%s\"\n"),gwarea->current); - debuga(_("searching for \'x%x\'\n"),stop); - //debuga(_("Maybe you have a broken record or garbage in your access.log file.\n")); + debuga(__FILE__,__LINE__,_("End of word not found in %s after %d bytes.\n"),__func__,x); + debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning); + debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current); + debuga(__FILE__,__LINE__,_("searching for \'x%x\'\n"),stop); if (limit>0) word[limit-1]='\0'; #if USE_GETWORD_BACKTRACE getword_backtrace(); @@ -151,11 +163,10 @@ int getword_skip(int limit, struct getwordstruct *gwarea, char stop) for(x=0;(gwarea->current[x] && (gwarea->current[x] != stop ));x++) { if(x>=limit) { - debuga(_("End of word not found in getword_skip after %d bytes.\n"),x); - debuga(_("Line=\"%s\"\n"),gwarea->beginning); - debuga(_("Record=\"%s\"\n"),gwarea->current); - debuga(_("searching for \'x%x\'\n"),stop); - //debuga(_("Maybe you have a broken record or garbage in your access.log file.\n")); + debuga(__FILE__,__LINE__,_("End of word not found in %s after %d bytes.\n"),__func__,x); + debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning); + debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current); + debuga(__FILE__,__LINE__,_("searching for \'x%x\'\n"),stop); #if USE_GETWORD_BACKTRACE getword_backtrace(); #endif @@ -184,17 +195,23 @@ int getword_atoll(long long int *number, struct getwordstruct *gwarea, char stop for(x=0;isdigit(gwarea->current[x]);x++) { digit=gwarea->current[x]-'0'; if (*number >= (LLONG_MAX-digit)/10) { - debuga(_("Integer overflow detected in getword_atoll in line %s\n"),gwarea->beginning); + /* + TRANSLATORS: The first %s is the function name (in the source code) where the + overflow is detected. + */ + debuga(__FILE__,__LINE__,_("Integer overflow detected in %s in line %s\n"),__func__,gwarea->beginning); return(-1); } *number=(*number * 10) + digit; } if(gwarea->current[x] && gwarea->current[x]!=stop) { - debuga(_("End of number not found in getword_atoll after %d bytes.\n"),x); - debuga(_("Line=\"%s\"\n"),gwarea->beginning); - debuga(_("Record=\"%s\"\n"),gwarea->current); - debuga(_("searching for \'x%x\'\n"),stop); - //debuga(_("Maybe you have a broken record or garbage in your access.log file.\n")); + /* + TRANSLATORS: The %s is the function name, in the source code, where the problem occured. + */ + debuga(__FILE__,__LINE__,_("End of number not found in %s after %d bytes.\n"),__func__,x); + debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning); + debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current); + debuga(__FILE__,__LINE__,_("searching for \'x%x\'\n"),stop); #if USE_GETWORD_BACKTRACE getword_backtrace(); #endif @@ -223,17 +240,16 @@ int getword_atoi(int *number, struct getwordstruct *gwarea, char stop) for(x=0;isdigit(gwarea->current[x]);x++) { digit=gwarea->current[x]-'0'; if (*number > (INT_MAX-digit)/10) { - debuga(_("Integer overflow detected in getword_atoi in line %s\n"),gwarea->beginning); + debuga(__FILE__,__LINE__,_("Integer overflow detected in %s in line %s\n"),__func__,gwarea->beginning); return(-1); } *number=(*number * 10) + digit; } if(gwarea->current[x] && gwarea->current[x]!=stop) { - debuga(_("End of number not found in getword_atoi after %d bytes.\n"),x); - debuga(_("Line=\"%s\"\n"),gwarea->beginning); - debuga(_("Record=\"%s\"\n"),gwarea->current); - debuga(_("searching for \'x%x\'\n"),stop); - //debuga(_("Maybe you have a broken record or garbage in your access.log file.\n")); + debuga(__FILE__,__LINE__,_("End of number not found in %s after %d bytes.\n"),__func__,x); + debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning); + debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current); + debuga(__FILE__,__LINE__,_("searching for \'x%x\'\n"),stop); #if USE_GETWORD_BACKTRACE getword_backtrace(); #endif @@ -248,7 +264,7 @@ int getword_atoi(int *number, struct getwordstruct *gwarea, char stop) int getword_atol(long int *number, struct getwordstruct *gwarea, char stop) { - long int x; + int x; long int sign=+1; int digit; @@ -262,17 +278,16 @@ int getword_atol(long int *number, struct getwordstruct *gwarea, char stop) for(x=0;isdigit(gwarea->current[x]);x++) { digit=gwarea->current[x]-'0'; if (*number > (LONG_MAX-digit)/10) { - debuga(_("Integer overflow detected in getword_atol in line %s\n"),gwarea->beginning); + debuga(__FILE__,__LINE__,_("Integer overflow detected in %s in line %s\n"),__func__,gwarea->beginning); return(-1); } *number=(*number * 10) + digit; } if(gwarea->current[x] && gwarea->current[x]!=stop) { - debuga(_("End of number not found in getword_atol after %ld bytes.\n"),x); - debuga(_("Line=\"%s\"\n"),gwarea->beginning); - debuga(_("Record=\"%s\"\n"),gwarea->current); - debuga(_("searching for \'x%x\'\n"),stop); - //debuga(_("Maybe you have a broken record or garbage in your access.log file.\n")); + debuga(__FILE__,__LINE__,_("End of number not found in %s after %d bytes.\n"),__func__,x); + debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning); + debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current); + debuga(__FILE__,__LINE__,_("searching for \'x%x\'\n"),stop); #if USE_GETWORD_BACKTRACE getword_backtrace(); #endif @@ -287,13 +302,13 @@ int getword_atol(long int *number, struct getwordstruct *gwarea, char stop) int getword_atolu(unsigned long int *number, struct getwordstruct *gwarea, char stop) { - unsigned long int x; + int x; int digit; if (gwarea->current[0] == '-') { - debuga(_("getword_atolu got a negative number.\n")); - debuga(_("Line=\"%s\"\n"),gwarea->beginning); - debuga(_("Record=\"%s\"\n"),gwarea->current); + debuga(__FILE__,__LINE__,_("getword_atolu got a negative number.\n")); + debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning); + debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current); return(-1); } if (gwarea->current[0] == '+') { @@ -303,17 +318,16 @@ int getword_atolu(unsigned long int *number, struct getwordstruct *gwarea, char for(x=0;isdigit(gwarea->current[x]);x++) { digit=gwarea->current[x]-'0'; if (*number > (ULONG_MAX-digit)/10) { - debuga(_("Integer overflow detected in getword_atolu in line %s\n"),gwarea->beginning); + debuga(__FILE__,__LINE__,_("Integer overflow detected in %s in line %s\n"),__func__,gwarea->beginning); return(-1); } *number=(*number * 10) + digit; } if(gwarea->current[x] && gwarea->current[x]!=stop) { - debuga(_("End of number not found in getword_atolu after %ld bytes.\n"),x); - debuga(_("Line=\"%s\"\n"),gwarea->beginning); - debuga(_("Record=\"%s\"\n"),gwarea->current); - debuga(_("searching for \'x%x\'\n"),stop); - //debuga(_("Maybe you have a broken record or garbage in your access.log file.\n")); + debuga(__FILE__,__LINE__,_("End of number not found in %s after %d bytes.\n"),__func__,x); + debuga(__FILE__,__LINE__,_("Line=\"%s\"\n"),gwarea->beginning); + debuga(__FILE__,__LINE__,_("Record=\"%s\"\n"),gwarea->current); + debuga(__FILE__,__LINE__,_("searching for \'x%x\'\n"),stop); #if USE_GETWORD_BACKTRACE getword_backtrace(); #endif @@ -339,7 +353,7 @@ int getword_ptr(char *orig_line,char **word, struct getwordstruct *gwarea, char int start; if (orig_line && orig_line!=gwarea->beginning) { - debuga(_("Invalid buffer passed to getword_ptr\n")); + debuga(__FILE__,__LINE__,_("Invalid buffer passed to getword_ptr\n")); return(-1); } @@ -380,12 +394,23 @@ long long int my_atoll (const char *nptr) int is_absolute(const char *path) { if (*path=='/') return(1); -#ifdef WINDOWS +#ifdef _WIN32 if (isalpha(path[0]) && path[1]==':') return(1); #endif return(0); } +int PortableMkDir(const char *path,int mode) +{ +#if defined(__linux__) + int mkerror=mkdir(path,mode); +#else //mingw + (void)mode; + int mkerror=_mkdir(path); +#endif + return(mkerror); +} + void my_mkdir(const char *name) { char w0[MAXLEN]; @@ -393,21 +418,22 @@ void my_mkdir(const char *name) int chars; if(!is_absolute(name)) { - debuga(_("Invalid path (%s). Please, use absolute paths only.\n"),name); + debuga(__FILE__,__LINE__,_("Invalid path (%s). Please, use absolute paths only.\n"),name); exit(EXIT_FAILURE); } chars=0; for (i=0 ; name[i] ; i++) { if (i>=sizeof(w0)) { - debuga(_("directory name too long: %s\n"),name); + debuga(__FILE__,__LINE__,_("Path too long: ")); + debuga_more("%s\n",name); exit(EXIT_FAILURE); } if (chars>0 && name[i] == '/') { w0[i] = '\0'; if (access(w0, R_OK) != 0) { - if (mkdir(w0,0755)) { - debuga(_("Cannot create directory %s - %s\n"),w0,strerror(errno)); + if (PortableMkDir(w0,0755)) { + debuga(__FILE__,__LINE__,_("Cannot create directory \"%s\": %s\n"),w0,strerror(errno)); exit(EXIT_FAILURE); } } @@ -417,8 +443,8 @@ void my_mkdir(const char *name) } if (access(name, R_OK) != 0) { - if (mkdir(name,0755)) { - debuga(_("Cannot create directory %s - %s\n"),name,strerror(errno)); + if (PortableMkDir(name,0755)) { + debuga(__FILE__,__LINE__,_("Cannot create directory \"%s\": %s\n"),name,strerror(errno)); exit(EXIT_FAILURE); } } @@ -434,7 +460,7 @@ void my_lltoa(unsigned long long int n, char *s, int ssize, int len) ssize--; if (len>ssize) { - debuga(_("The requested number of digits passed to my_lltoa (%d) is bigger than the output buffer size (%d)\n"),len,ssize); + debuga(__FILE__,__LINE__,_("The requested number of digits passed to my_lltoa (%d) is bigger than the output buffer size (%d)\n"),len,ssize); abort(); } @@ -481,7 +507,7 @@ Compare two dates. \retval 0 If date1==date2. \retval 1 if date1>date2. */ -int compare_date(struct tm *date1,struct tm *date2) +int compare_date(const struct tm *date1,const struct tm *date2) { if (date1->tm_yeartm_year) return(-1); if (date1->tm_year>date2->tm_year) return(1); @@ -498,12 +524,12 @@ int compare_date(struct tm *date1,struct tm *date2) return(0); } -void buildymd(const char *dia, const char *mes, const char *ano, char *wdata) +void buildymd(const char *dia, const char *mes, const char *ano, char *wdata,int wdata_size) { int nmes; nmes=month2num(mes); - sprintf(wdata,"%04d%02d%02d",atoi(ano),nmes+1,atoi(dia)); + snprintf(wdata,wdata_size,"%04d%02d%02d",atoi(ano),nmes+1,atoi(dia)); } @@ -527,57 +553,75 @@ const char *conv_month_name(int month) return(mtab1[month-1]); } +/*! +Write a debug message to stderr. The message is prefixed by "SARG:" to identify its origin. -void name_month(char *month,int month_len) +\param msg The printf like message to format. +\param ... The arguments to format in the message. +*/ +void debuga(const char *File,int Line,const char *msg,...) { - int x, z=atoi(month)-1; - char m[255]; - char w[20]; - struct getwordstruct gwarea; - - strcpy(m,_("January,February,March,April,May,June,July,August,September,October,November,December")); - getword_start(&gwarea,m); + va_list ap; - for(x=0; x=LogLevel_Source) { + /* The path is removed because every source file is in the same directory. + * There is no point in reporting the full path from the build directory. + */ + const char *ptr=strrchr(File,'/'); + if (!ptr) ptr=File; + /* TRANSLATORS: This is the prefix to stderr messages when the debug level is + set to display the source file (%s) and the line number (%d). */ + fprintf(stderr,_("SARG(%s:%d): "),ptr,Line); + } else { + /* TRANSLATORS: This is the prefix to stderr messages when the debug level + is low. */ + fputs(_("SARG: "),stderr); } + va_start(ap,msg); + vfprintf(stderr,msg,ap); + va_end(ap); } - /*! -Write a debug message to stderr. The message is prefixed by "SARG:" to identify its origin. +Write a debug message to stderr. The message is supposed +to be displayed after a message from debuga(). \param msg The printf like message to format. \param ... The arguments to format in the message. */ -void debuga(const char *msg,...) +void debuga_more(const char *msg,...) { va_list ap; - fputs(_("SARG: "),stderr); va_start(ap,msg); vfprintf(stderr,msg,ap); va_end(ap); } - /*! Write a debug message to stderr. The message is prefixed by "SARG: (info)". \param msg The printf like message to format. \param ... The arguments to format in the message. */ -void debugaz(const char *msg,...) +void debugaz(const char *File,int Line,const char *msg,...) { va_list ap; - fputs(_("SARG: (info) "),stderr); + if (debugz>=LogLevel_Source) { + /* The path is removed because every source file is in the same directory. + * There is no point in reporting the full path from the build directory. + */ + const char *ptr=strrchr(File,'/'); + if (!ptr) ptr=File; + /* TRANSLATORS: This is the prefix to information messages when the debug level is + set to display the source file (%s) and the line number (%d). */ + fprintf(stderr,_("SARG(%s:%d): (info) "),ptr,Line); + } else { + /* TRANSLATORS: This is the prefix to information messages when the debug level + is low. */ + fputs(_("SARG: (info) "),stderr); + } va_start(ap,msg); vfprintf(stderr,msg,ap); va_end(ap); @@ -594,61 +638,65 @@ char *fixnum(long long int value, int n) char *pret; register int i, j, k; int numlen; - static char abbrev[30]; + static char abbrev[30]=""; my_lltoa(value, num, sizeof(num), 0); if(DisplayedValues==DISPLAY_ABBREV) { numlen = strlen(num); if(numlen <= 3) - sprintf(abbrev,"%s",num); - if(numlen == 4 || numlen == 7 || numlen == 10 || numlen == 13) { - snprintf(abbrev,2,"%s",num); - strncat(abbrev,".",1); - strncat(abbrev,num+1,2); - if(!n) return(abbrev); - if(numlen == 4) - strncat(abbrev,"K",1); - else if(numlen == 7) - strncat(abbrev,"M",1); - else if(numlen == 10) - strncat(abbrev,"G",1); - else if(numlen == 13) - strncat(abbrev,"T",1); - } - if(numlen == 5 || numlen == 8 || numlen == 11 || numlen == 14) { - snprintf(abbrev,3,"%s",num); - strncat(abbrev,".",1); - strncat(abbrev,num+2,2); - if(!n) return(abbrev); - if(numlen == 5) - strncat(abbrev,"K",1); - else if(numlen == 8) - strncat(abbrev,"M",1); - else if(numlen == 11) - strncat(abbrev,"G",1); - else if(numlen == 14) - strncat(abbrev,"T",1); - } - if(numlen == 6 || numlen == 9 || numlen == 12 || numlen == 15) { - snprintf(abbrev,4,"%s",num); - strncat(abbrev,".",1); - strncat(abbrev,num+3,2); - if(!n) return(abbrev); - if(numlen == 6) - strncat(abbrev,"K",1); - else if(numlen == 9) - strncat(abbrev,"M",1); - else if(numlen == 12) - strncat(abbrev,"G",1); - else if(numlen == 15) - strncat(abbrev,"T",1); + strcpy(abbrev,num); + else if (numlen%3 == 1) { + abbrev[0]=num[0]; + abbrev[1]=(UseComma) ? ',' : '.'; + abbrev[2]=num[1]; + abbrev[3]=num[2]; + abbrev[4]='\0'; + } + else if (numlen%3 == 2) { + abbrev[0]=num[0]; + abbrev[1]=num[1]; + abbrev[2]=(UseComma) ? ',' : '.'; + abbrev[3]=num[2]; + abbrev[4]=num[3]; + abbrev[5]='\0'; + } + else if (numlen%3 == 0) { + abbrev[0]=num[0]; + abbrev[1]=num[1]; + abbrev[2]=num[2]; + abbrev[3]=(UseComma) ? ',' : '.'; + abbrev[4]=num[3]; + abbrev[5]=num[4]; + abbrev[6]='\0'; + } + if (n) { + if (numlen <= 3) { + //no prefix + } + else if (numlen <= 6) + strcat(abbrev,"K"); + else if (numlen <= 9) + strcat(abbrev,"M"); + else if (numlen <= 12) + strcat(abbrev,"G"); + else if (numlen <= 15) + strcat(abbrev,"T"); + else if (numlen >= 18) + strcat(abbrev,"P"); + else if (numlen <= 21) + strcat(abbrev,"E"); + else if (numlen <= 24) + strcat(abbrev,"Z"); + else if (numlen <= 27) + strcat(abbrev,"Y"); + else + strcat(abbrev,"???"); } - return(abbrev); } - bzero(buf, MAXLEN_FIXNUM*2); + memset(buf,0,MAXLEN_FIXNUM*2); pbuf = buf; pret = ret; @@ -688,7 +736,7 @@ char *fixnum2(long long int value, int n) register int i, j, k; my_lltoa(value, num, sizeof(num), 0); - bzero(buf, MAXLEN_FIXNUM2*2); + memset(buf,0,MAXLEN_FIXNUM2*2); pbuf = buf; pret = ret; @@ -719,18 +767,16 @@ char *fixnum2(long long int value, int n) char *buildtime(long long int elap) { - int num = elap / 1000; + long int num = elap / 1000LL; int hor = 0; int min = 0; int sec = 0; - static char buf[12]; - - buf[0]='\0'; + static char buf[20]; - hor=num / 3600; - min=(num % 3600) / 60; - sec=num % 60; - sprintf(buf,"%02d:%02d:%02d",hor,min,sec); + hor=num / 3600L; + min=(num % 3600L) / 60L; + sec=num % 60L; + snprintf(buf,sizeof(buf),"%02d:%02d:%02d",hor,min,sec); return(buf); } @@ -752,9 +798,17 @@ int obtdate(const char *dirname, const char *name, char *data) FILE *fp_in; char wdir[MAXLEN]; - sprintf(wdir,"%s%s/sarg-date",dirname,name); + if (snprintf(wdir,sizeof(wdir),"%s%s/sarg-date",dirname,name)>=sizeof(wdir)) { + debuga(__FILE__,__LINE__,_("Buffer too small to store ")); + debuga_more("%s%s/sarg-date",dirname,name); + exit(EXIT_FAILURE); + } if ((fp_in = fopen(wdir, "rt")) == 0) { - sprintf(wdir,"%s%s/date",dirname,name); + if (snprintf(wdir,sizeof(wdir),"%s%s/date",dirname,name)>=sizeof(wdir)) { + debuga(__FILE__,__LINE__,_("Buffer too small to store ")); + debuga_more("%s%s/date",dirname,name); + exit(EXIT_FAILURE); + } if ((fp_in = fopen(wdir, "rt")) == 0) { data[0]='\0'; return(-1); @@ -762,10 +816,13 @@ int obtdate(const char *dirname, const char *name, char *data) } if (!fgets(data,80,fp_in)) { - debuga(_("Failed to read the date in %s\n"),wdir); + debuga(__FILE__,__LINE__,_("Failed to read the date in file \"%s\"\n"),wdir); + exit(EXIT_FAILURE); + } + if (fclose(fp_in)==EOF) { + debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),wdir,strerror(errno)); exit(EXIT_FAILURE); } - fclose(fp_in); fixendofline(data); return(0); @@ -809,19 +866,30 @@ int obtuser(const char *dirname, const char *name) char tuser[20]; int nuser; - sprintf(wdir,"%s%s/sarg-users",dirname,name); + if (snprintf(wdir,sizeof(wdir),"%s%s/sarg-users",dirname,name)>=sizeof(wdir)) { + debuga(__FILE__,__LINE__,_("Buffer too small to store ")); + debuga_more("%s%s/sarg-users",dirname,name); + exit(EXIT_FAILURE); + } if((fp_in=fopen(wdir,"r"))==NULL) { - sprintf(wdir,"%s%s/users",dirname,name); + if (snprintf(wdir,sizeof(wdir),"%s%s/users",dirname,name)>=sizeof(wdir)) { + debuga(__FILE__,__LINE__,_("Buffer too small to store ")); + debuga_more("%s%s/users",dirname,name); + exit(EXIT_FAILURE); + } if((fp_in=fopen(wdir,"r"))==NULL) { return(0); } } if (!fgets(tuser,sizeof(tuser),fp_in)) { - debuga(_("Failed to read the number of users in %s\n"),wdir); + debuga(__FILE__,__LINE__,_("Failed to read the number of users in file \"%s\"\n"),wdir); + exit(EXIT_FAILURE); + } + if (fclose(fp_in)==EOF) { + debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),wdir,strerror(errno)); exit(EXIT_FAILURE); } - fclose(fp_in); nuser=atoi(tuser); return(nuser); @@ -830,7 +898,7 @@ int obtuser(const char *dirname, const char *name) void obttotal(const char *dirname, const char *name, int nuser, long long int *tbytes, long long int *media) { - FILE *fp_in; + FileObject *fp_in; char *buf; char wdir[MAXLEN]; char user[MAX_USER_LEN]; @@ -841,16 +909,24 @@ void obttotal(const char *dirname, const char *name, int nuser, long long int *t *tbytes=0; *media=0; - sprintf(wdir,"%s%s/sarg-general",dirname,name); - if ((fp_in = fopen(wdir, "r")) == 0) { - sprintf(wdir,"%s%s/general",dirname,name); - if ((fp_in = fopen(wdir, "r")) == 0) { + if (snprintf(wdir,sizeof(wdir),"%s%s/sarg-general",dirname,name)>=sizeof(wdir)) { + debuga(__FILE__,__LINE__,_("Buffer too small to store ")); + debuga_more("%s%s/sarg-general",dirname,name); + exit(EXIT_FAILURE); + } + if ((fp_in = FileObject_Open(wdir)) == NULL) { + if (snprintf(wdir,sizeof(wdir),"%s%s/general",dirname,name)>=sizeof(wdir)) { + debuga(__FILE__,__LINE__,_("Buffer too small to store ")); + debuga_more("%s%s/general",dirname,name); + exit(EXIT_FAILURE); + } + if ((fp_in = FileObject_Open(wdir)) == NULL) { return; } } if ((line=longline_create())==NULL) { - debuga(_("Not enough memory to read the file %s\n"),wdir); + debuga(__FILE__,__LINE__,_("Not enough memory to read file \"%s\"\n"),wdir); exit(EXIT_FAILURE); } @@ -863,22 +939,25 @@ void obttotal(const char *dirname, const char *name, int nuser, long long int *t continue; getword_start(&gwarea,buf); if (getword(user,sizeof(user),&gwarea,sep)<0) { - debuga(_("There is a invalid user in file %s\n"),wdir); + debuga(__FILE__,__LINE__,_("Invalid user in file \"%s\"\n"),wdir); exit(EXIT_FAILURE); } if(strcmp(user,"TOTAL") != 0) continue; if (getword_skip(MAXLEN,&gwarea,sep)<0) { - debuga(_("There a broken total number of access in file %s\n"),wdir); + debuga(__FILE__,__LINE__,_("Invalid total number of accesses in file \"%s\"\n"),wdir); exit(EXIT_FAILURE); } if (getword_atoll(tbytes,&gwarea,sep)<0) { - debuga(_("There is a broken number of bytes in file %s\n"),wdir); + debuga(__FILE__,__LINE__,_("Invalid number of bytes in file \"%s\"\n"),wdir); exit(EXIT_FAILURE); } break; } - fclose(fp_in); + if (FileObject_Close(fp_in)) { + debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),wdir,FileObject_GetLastCloseError()); + exit(EXIT_FAILURE); + } longline_destroy(&line); if (nuser <= 0) @@ -909,7 +988,7 @@ int getperiod_fromsarglog(const char *arqtt,struct periodstruct *period) str+=2; year0=0; for (i=0 ; isdigit(str[i]) && i<4 ; i++) year0=year0*10+(str[i]-'0'); - if (i!=4) continue; + if (i!=4 || year0<1900) continue; str+=4; if (str[0]!='_') continue; str++; @@ -933,7 +1012,7 @@ int getperiod_fromsarglog(const char *arqtt,struct periodstruct *period) str+=2; year1=0; for (i=0 ; isdigit(str[i]) && i<4 ; i++) year1=year1*10+(str[i]-'0'); - if (i!=4) continue; + if (i!=4 || year1<1900) continue; str+=4; if (str[0]!='_') continue; @@ -961,6 +1040,13 @@ int getperiod_fromsarglog(const char *arqtt,struct periodstruct *period) return(-1); } +/*! +Fill the period with the specified range. + +\param period The period to change. +\param dfrom The start date in the form year*10000+month*100+day. +\param duntil The end date in the form year*10000+month*100+day. +*/ void getperiod_fromrange(struct periodstruct *period,int dfrom,int duntil) { memset(&period->start,0,sizeof(period->start)); @@ -974,6 +1060,21 @@ void getperiod_fromrange(struct periodstruct *period,int dfrom,int duntil) period->end.tm_year=(duntil/10000)-1900; } +/*! +Get the range from a period. + +\param period The period to convert to a range. +\param dfrom The variable to store the range beginning. It can be NULL. +\param duntil The variable to store the range end. It can be NULL. +*/ +void getperiod_torange(const struct periodstruct *period,int *dfrom,int *duntil) +{ + if (dfrom) + *dfrom=(period->start.tm_year+1900)*10000+(period->start.tm_mon+1)*100+period->start.tm_mday; + if (duntil) + *duntil=(period->end.tm_year+1900)*10000+(period->end.tm_mon+1)*100+period->end.tm_mday; +} + /*! Update the \a main period to encompass the period in \a candidate. */ @@ -984,7 +1085,7 @@ void getperiod_merge(struct periodstruct *main,struct periodstruct *candidate) mdate=(main->start.tm_year)*10000+(main->start.tm_mon)*100+main->start.tm_mday; cdate=(candidate->start.tm_year)*10000+(candidate->start.tm_mon)*100+candidate->start.tm_mday; - if (cdatestart,&candidate->start,sizeof(struct tm)); + if (mdate==0 || cdatestart,&candidate->start,sizeof(struct tm)); mdate=(main->end.tm_year)*10000+(main->end.tm_mon)*100+main->end.tm_mday; cdate=(candidate->end.tm_year)*10000+(candidate->end.tm_mon)*100+candidate->end.tm_mday; @@ -1035,7 +1136,6 @@ static void copy_images(void) { FILE *img_in, *img_ou; char images[512]; - char imgdir[MAXLEN]; char srcfile[MAXLEN]; char dstfile[MAXLEN]; DIR *dirp; @@ -1045,51 +1145,61 @@ static void copy_images(void) struct stat info; if (snprintf(images,sizeof(images),"%simages",outdir)>=sizeof(images)) { - debuga(_("Cannot copy images to target directory %simages\n"),outdir); + debuga(__FILE__,__LINE__,_("Cannot copy images to target directory %simages\n"),outdir); exit(EXIT_FAILURE); } if (access(images,R_OK)!=0) { - if (mkdir(images,0755)) { - debuga(_("Cannot create directory %s - %s\n"),images,strerror(errno)); + if (PortableMkDir(images,0755)) { + debuga(__FILE__,__LINE__,_("Cannot create directory \"%s\": %s\n"),images,strerror(errno)); exit(EXIT_FAILURE); } } - strcpy(imgdir,IMAGEDIR); - dirp = opendir(imgdir); + dirp = opendir(ImageDir); if(dirp==NULL) { - debuga(_("(util) Can't open directory %s: %s\n"),imgdir,strerror(errno)); + debuga(__FILE__,__LINE__,_("Cannot open directory \"%s\": %s\n"),ImageDir,strerror(errno)); return; } while ((direntp = readdir( dirp )) != NULL ){ if(direntp->d_name[0]=='.') continue; - sprintf(srcfile,"%s/%s",imgdir,direntp->d_name); + if (snprintf(srcfile,sizeof(srcfile),"%s/%s",ImageDir,direntp->d_name)>=sizeof(srcfile)) { + debuga(__FILE__,__LINE__,_("Buffer too small to store ")); + debuga_more("%s/%s",ImageDir,direntp->d_name); + exit(EXIT_FAILURE); + } if (stat(srcfile,&info)) { - debuga(_("Cannot stat \"%s\" - %s\n"),srcfile,strerror(errno)); + debuga(__FILE__,__LINE__,_("Cannot stat \"%s\": %s\n"),srcfile,strerror(errno)); continue; } if (S_ISREG(info.st_mode)) { - sprintf(dstfile,"%s/%s",images,direntp->d_name); + if (snprintf(dstfile,sizeof(dstfile),"%s/%s",images,direntp->d_name)>=sizeof(dstfile)) { + debuga(__FILE__,__LINE__,_("Buffer too small to store ")); + debuga_more("%s/%s",images,direntp->d_name); + exit(EXIT_FAILURE); + } img_in = fopen(srcfile, "rb"); if(img_in!=NULL) { img_ou = fopen(dstfile, "wb"); if(img_ou!=NULL) { while ((nread = fread(buffer,1,sizeof(buffer),img_in))>0) { if (fwrite(buffer,1,nread,img_ou)!=nread) { - debuga(_("Failed to copy image %s to %s\n"),srcfile,dstfile); + debuga(__FILE__,__LINE__,_("Failed to copy image %s to %s\n"),srcfile,dstfile); break; } } if (fclose(img_ou)==EOF) { - debuga(_("Error while copying image %s: %s\n"),dstfile,strerror(errno)); + debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),dstfile,strerror(errno)); exit(EXIT_FAILURE); } } else - fprintf(stderr,"SARG: (util): %s %s: %s\n", _("Cannot open file")?_("Cannot open file"):"Can't open/create file", dstfile, strerror(errno)); - fclose(img_in); + debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"), dstfile, strerror(errno)); + if (fclose(img_in)==EOF) { + debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),srcfile,strerror(errno)); + exit(EXIT_FAILURE); + } } else - fprintf(stderr,"SARG: (util): %s %s: %s\n", _("Cannot open file")?_("Cannot open file"):"Can't open file", srcfile, strerror(errno)); + debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"), srcfile, strerror(errno)); } } (void) closedir(dirp); @@ -1097,12 +1207,186 @@ static void copy_images(void) return; } -int vrfydir(const struct periodstruct *per1, const char *addr, const char *site, const char *us, const char *form) +/*! + * 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 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); +} + +/*! + * Create a directory to generate a report for the specified connection data + * and populate it with the a sarg-date file containing the current + * date. + * + * The function also create an images directory in \a dir and copy all + * the files from the SYSCONFDIR/images into that directory. + * + * \param per1 The date range in the form: YYYYMMMDD-YYYYMMMDD or DDMMMYYYY-DDMMMYYYY depending on the value of + * ::DateFormat. + * \param addr The ip address or host name to which the report is limited. If the string is empty, all the addresses are accepted. + * \param site The destination site to which the report is limited. If the string is empty, all the sites are accepted. + * \param us The user to whom the report is limited. It is an empty string if all the users are accepted. + */ +int vrfydir(const struct periodstruct *per1, const char *addr, const char *site, const char *us) { FILE *fp_ou; - int num=1, count=0; char wdir[MAXLEN]; - char dirname2[MAXLEN]; int y1, y2; int m1, m2; int d1, d2; @@ -1163,61 +1447,35 @@ int vrfydir(const struct periodstruct *per1, const char *addr, const char *site, strcpy(outdirname,wdir); - if(IndexTree != INDEX_TREE_DATE) { - if(!OverwriteReport) { - while(num) { - if(access(wdir,R_OK) == 0) { - sprintf(wdir,"%s.%d",outdirname,num); - num++; - count++; - } else - break; - } + // manufacture a new unique name if configured to keep old reports or overwrite old report if configured to do so + if (!OverwriteReport) { + int num=1; - if(count > 0) { - if(debug) - debuga(_("File %s already exists, moved to %s\n"),outdirname,wdir); - rename(outdirname,wdir); - } - } else { - if(access(outdirname,R_OK) == 0) { - unlinkdir(outdirname,1); - } + while (access(wdir,R_OK)==0 || errno==EACCES) //file exist or can't be read + { + sprintf(wdir,"%s.%d",outdirname,num); + num++; + } + if (num>1) { + if(debug) + debuga(__FILE__,__LINE__,_("File %s already exists, moved to %s\n"),outdirname,wdir); + rename(outdirname,wdir); } - my_mkdir(outdirname); } else { - strcpy(dirname2,wdir); - if(!OverwriteReport) { - while(num) { - if(access(wdir,R_OK) == 0) { - sprintf(wdir,"%s.%d",dirname2,num); - num++; - count++; - } else - break; - } - - if(count > 0) { - if(debug) - debuga(_("File %s already exists, moved to %s\n"),dirname2,wdir); - rename(dirname2,wdir); - strcpy(dirname2,wdir); - } - } else { - if(access(wdir,R_OK) == 0) { - unlinkdir(wdir,1); - } + if(access(outdirname,R_OK) == 0) { + unlinkdir(outdirname,1); } - - if(access(wdir, R_OK) != 0) - my_mkdir(wdir); } + my_mkdir(outdirname); - strcpy(dirname2,wdir); - - sprintf(wdir,"%s/sarg-date",outdirname); + // create sarg-date to keep track of the report creation date + if (snprintf(wdir,sizeof(wdir),"%s/sarg-date",outdirname)>=sizeof(wdir)) { + debuga(__FILE__,__LINE__,_("Buffer too small to store ")); + debuga_more("%s/sarg-date",outdirname); + exit(EXIT_FAILURE); + } if ((fp_ou = fopen(wdir, "wt")) == 0) { - debuga(_("cannot open %s for writing: %s\n"),wdir,strerror(errno)); + debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),wdir,strerror(errno)); perror("SARG:"); exit(EXIT_FAILURE); } @@ -1226,12 +1484,12 @@ int vrfydir(const struct periodstruct *per1, const char *addr, const char *site, loctm=localtime(&curtime); strftime(wdir,sizeof(wdir),"%Y-%m-%d %H:%M:%S",loctm); if (fprintf(fp_ou,"%s %d\n",wdir,loctm->tm_isdst)<0) { - debuga(_("Failed to write the date in %s\n"),wdir); + debuga(__FILE__,__LINE__,_("Failed to write the date in %s\n"),wdir); perror("SARG:"); exit(EXIT_FAILURE); } if (fclose(fp_ou)==EOF) { - debuga(_("Failed to write the date in %s: %s\n"),wdir,strerror(errno)); + debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),wdir,strerror(errno)); exit(EXIT_FAILURE); } @@ -1251,7 +1509,7 @@ int vrfydir(const struct periodstruct *per1, const char *addr, const char *site, void safe_strcpy(char *dest,const char *src,int length) { if (length<=0) { - debuga(_("Invalid buffer length passed to the function to safely copy a string\n")); + debuga(__FILE__,__LINE__,_("Invalid buffer length passed to the function to safely copy a string\n")); exit(EXIT_FAILURE); } strncpy(dest,src,length-1); @@ -1298,26 +1556,26 @@ void zdate(char *ftime,int ftimesize, char DateFormat) char *fixtime(long long int elap) { - int num = elap / 1000; + long int num = elap / 1000LL; int hor = 0; int min = 0; int sec = 0; - static char buf[12]; + static char buf[20]; - hor=num / 3600; - min=(num % 3600) / 60; - sec=num % 60; + hor=num / 3600L; + min=(num % 3600L) / 60L; + sec=num % 60L; if(hor==0 && min==0 && sec==0) strcpy(buf,"0"); else - sprintf(buf,"%d:%02d:%02d",hor,min,sec); + snprintf(buf,sizeof(buf),"%d:%02d:%02d",hor,min,sec); return buf; } -void date_from(char *date, int *dfrom, int *duntil) +void date_from(char *date,int date_size, int *dfrom, int *duntil) { int d0=0; int m0=0; @@ -1330,16 +1588,16 @@ void date_from(char *date, int *dfrom, int *duntil) int next=-1; if (sscanf(date,"%d/%d/%d%n",&d0,&m0,&y0,&next)!=3 || y0<100 || m0<1 || m0>12 || d0<1 || d0>31 || next<0) { - debuga(_("The date passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n")); + debuga(__FILE__,__LINE__,_("The date passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n")); exit(EXIT_FAILURE); } if (date[next]=='-') { if (sscanf(date+next+1,"%d/%d/%d",&d1,&m1,&y1)!=3 || y1<100 || m1<1 || m1>12 || d1<1 || d1>31) { - debuga(_("The date range passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n")); + debuga(__FILE__,__LINE__,_("The date range passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n")); exit(EXIT_FAILURE); } } else if (date[next]!='\0') { - debuga(_("The date range passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n")); + debuga(__FILE__,__LINE__,_("The date range passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n")); exit(EXIT_FAILURE); } else { d1=d0; @@ -1352,18 +1610,18 @@ void date_from(char *date, int *dfrom, int *duntil) struct tm *Date0,Date1; if (time(&Today)==(time_t)-1) { - debuga(_("Failed to get the current time\n")); + debuga(__FILE__,__LINE__,_("Failed to get the current time\n")); exit(EXIT_FAILURE); } if (sscanf(date,"day-%d",&i)==1) { if (i<0) { - debuga(_("Invalid number of days in -d parameter\n")); + debuga(__FILE__,__LINE__,_("Invalid number of days in -d parameter\n")); exit(EXIT_FAILURE); } Today-=i*24*60*60; Date0=localtime(&Today); if (Date0==NULL) { - debuga(_("Cannot convert local time: %s\n"),strerror(errno)); + debuga(__FILE__,__LINE__,_("Cannot convert local time: %s\n"),strerror(errno)); exit(EXIT_FAILURE); } y0=y1=Date0->tm_year+1900; @@ -1382,19 +1640,19 @@ void date_from(char *date, int *dfrom, int *duntil) time_t WeekBegin; if (i<0) { - debuga(_("Invalid number of weeks in -d parameter\n")); + debuga(__FILE__,__LINE__,_("Invalid number of weeks in -d parameter\n")); exit(EXIT_FAILURE); } Date0=localtime(&Today); if (Date0==NULL) { - debuga(_("Cannot convert local time: %s\n"),strerror(errno)); + debuga(__FILE__,__LINE__,_("Cannot convert local time: %s\n"),strerror(errno)); exit(EXIT_FAILURE); } WeekBegin=Today-((Date0->tm_wday-FirstWeekDay+7)%7)*24*60*60; WeekBegin-=i*7*24*60*60; Date0=localtime(&WeekBegin); if (Date0==NULL) { - debuga(_("Cannot convert local time: %s\n"),strerror(errno)); + debuga(__FILE__,__LINE__,_("Cannot convert local time: %s\n"),strerror(errno)); exit(EXIT_FAILURE); } y0=Date0->tm_year+1900; @@ -1403,7 +1661,7 @@ void date_from(char *date, int *dfrom, int *duntil) WeekBegin+=6*24*60*60; Date0=localtime(&WeekBegin); if (Date0==NULL) { - debuga(_("Cannot convert local time: %s\n"),strerror(errno)); + debuga(__FILE__,__LINE__,_("Cannot convert local time: %s\n"),strerror(errno)); exit(EXIT_FAILURE); } y1=Date0->tm_year+1900; @@ -1411,12 +1669,12 @@ void date_from(char *date, int *dfrom, int *duntil) d1=Date0->tm_mday; } else if (sscanf(date,"month-%d",&i)==1) { if (i<0) { - debuga(_("Invalid number of months in -d parameter\n")); + debuga(__FILE__,__LINE__,_("Invalid number of months in -d parameter\n")); exit(EXIT_FAILURE); } Date0=localtime(&Today); if (Date0==NULL) { - debuga(_("Cannot convert local time: %s\n"),strerror(errno)); + debuga(__FILE__,__LINE__,_("Cannot convert local time: %s\n"),strerror(errno)); exit(EXIT_FAILURE); } if (Date0->tm_montm_mon+1; d1=Date0->tm_mday; } else { - debuga(_("Invalid date range passed on command line\n")); + debuga(__FILE__,__LINE__,_("Invalid date range passed on command line\n")); exit(EXIT_FAILURE); } } *dfrom=y0*10000+m0*100+d0; *duntil=y1*10000+m1*100+d1; - sprintf(date,"%02d/%02d/%04d-%02d/%02d/%04d",d0,m0,y0,d1,m1,y1); + snprintf(date,date_size,"%02d/%02d/%04d-%02d/%02d/%04d",d0,m0,y0,d1,m1,y1); return; } @@ -1496,19 +1754,20 @@ void removetmp(const char *outdir) return; if(debug) { - debuga(_("Purging temporary file sarg-general\n")); + debuga(__FILE__,__LINE__,_("Purging temporary file sarg-general\n")); } if (snprintf(filename,sizeof(filename),"%s/sarg-general",outdir)>=sizeof(filename)) { - debuga(_("(removetmp) directory too long to remove %s/sarg-period\n"),outdir); + debuga(__FILE__,__LINE__,_("Path too long: ")); + debuga_more("%s/sarg-period\n",outdir); exit(EXIT_FAILURE); } if((fp_gen=fopen(filename,"w"))==NULL){ - debuga(_("(removetmp) Cannot open file %s: %s\n"),filename,strerror(errno)); + debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),filename,strerror(errno)); exit(EXIT_FAILURE); } totalger(fp_gen,filename); if (fclose(fp_gen)==EOF) { - debuga(_("Failed to close %s after writing the total line: %s\n"),filename,strerror(errno)); + debuga(__FILE__,__LINE__,_("Write error in \"%s\": %s\n"),filename,strerror(errno)); exit(EXIT_FAILURE); } } @@ -1525,27 +1784,27 @@ void load_excludecodes(const char *ExcludeCodes) return; if((fp_in=fopen(ExcludeCodes,"r"))==NULL) { - debuga(_("(util) Cannot open file %s (exclude_codes): %s\n"),ExcludeCodes,strerror(errno)); + debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),ExcludeCodes,strerror(errno)); exit(EXIT_FAILURE); } if (fseek(fp_in, 0, SEEK_END)==-1) { - debuga(_("Failed to move till the end of the excluded codes file %s: %s\n"),ExcludeCodes,strerror(errno)); + debuga(__FILE__,__LINE__,_("Failed to move till the end of file \"%s\": %s\n"),ExcludeCodes,strerror(errno)); exit(EXIT_FAILURE); } MemSize = ftell(fp_in); if (MemSize<0) { - debuga(_("Cannot get the size of file %s\n"),ExcludeCodes); + debuga(__FILE__,__LINE__,_("Cannot get the size of file \"%s\"\n"),ExcludeCodes); exit(EXIT_FAILURE); } if (fseek(fp_in, 0, SEEK_SET)==-1) { - debuga(_("Failed to rewind the excluded codes file %s: %s\n"),ExcludeCodes,strerror(errno)); + debuga(__FILE__,__LINE__,_("Failed to rewind file \"%s\": %s\n"),ExcludeCodes,strerror(errno)); exit(EXIT_FAILURE); } MemSize+=1; if((excludecode=(char *) malloc(MemSize))==NULL) { - debuga(_("malloc error (%ld)\n"),MemSize); + debuga(__FILE__,__LINE__,_("malloc error (%ld bytes required)\n"),MemSize); exit(EXIT_FAILURE); } memset(excludecode,0,MemSize); @@ -1556,7 +1815,7 @@ void load_excludecodes(const char *ExcludeCodes) for (i=strlen(data)-1 ; i>=0 && (unsigned char)data[i]<=' ' ; i--) data[i]='\0'; if (i<0) continue; if (Stored+i+2>=MemSize) { - debuga(_("Too many codes to exclude in file %s\n"),ExcludeCodes); + debuga(__FILE__,__LINE__,_("Too many codes to exclude in file \"%s\"\n"),ExcludeCodes); break; } strcat(excludecode,data); @@ -1564,7 +1823,10 @@ void load_excludecodes(const char *ExcludeCodes) Stored+=i+1; } - fclose(fp_in); + if (fclose(fp_in)==EOF) { + debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),ExcludeCodes,strerror(errno)); + exit(EXIT_FAILURE); + } return; } @@ -1701,37 +1963,6 @@ int getnumlist( char *buf, numlist *list, const int len, const int maxvalue ) return 0; } - -char *get_size(const char *path, const char *file) -{ - FILE *fp; - static char response[255]; - char cmd[255]; - char *ptr; - - if (snprintf(cmd,sizeof(cmd),"du -skh %s%s",path,file)>=sizeof(cmd)) { - debuga(_("Cannot get disk space because the path %s%s is too long\n"),path,file); - exit(EXIT_FAILURE); - } - if ((fp = popen(cmd, "r")) == NULL) { - debuga(_("Cannot get disk space with command %s\n"),cmd); - exit(EXIT_FAILURE); - } - if (!fgets(response, sizeof(response), fp)) { - debuga(_("Cannot get disk size with command %s\n"),cmd); - exit(EXIT_FAILURE); - } - ptr=strchr(response,'\t'); - if (ptr==NULL) { - debuga(_("The command %s failed\n"),cmd); - exit(EXIT_FAILURE); - } - pclose(fp); - *ptr='\0'; - - return (response); -} - void show_info(FILE *fp_ou) { char ftime[127]; @@ -1739,7 +1970,7 @@ void show_info(FILE *fp_ou) if(!ShowSargInfo) return; zdate(ftime, sizeof(ftime), df); fputs("
",fp_ou); - fprintf(fp_ou,_("Generated by %s-%s on %s"),URL,PGM,VERSION,ftime); + fprintf(fp_ou,_("Generated by %s-%s on %s"),URL,PGM,VERSION,ftime); fputs("
\n",fp_ou); } @@ -1792,11 +2023,10 @@ void close_html_header(FILE *fp_ou) fputs("\n",fp_ou); } -int write_html_trailer(FILE *fp_ou) +void write_html_trailer(FILE *fp_ou) { show_info(fp_ou); - if (fputs("\n\n",fp_ou)==EOF) return(-1); - return(0); + fputs("\n\n",fp_ou); } void output_html_string(FILE *fp_ou,const char *str,int maxlen) @@ -1939,6 +2169,26 @@ void url_to_anchor(const char *url,char *anchor,int size) void version(void) { printf(_("SARG Version: %s\n"),VERSION); +#if defined(ENABLE_NLS) && defined(HAVE_LOCALE_H) + if (debug) { + printf(_("\nFor the translation to work, a valid message file should be copied to " + "\"%s//LC_MESSAGES/%s.mo\" where is derived from the effective locale.\n"),LOCALEDIR,PACKAGE_NAME); + if (CurrentLocale) { + printf(_("Currently effective locale is \"%s\".\n"),CurrentLocale); + } else { + printf(_("Locale is not set in the environment variable.\n")); + } + // TRANSLATORS: You may change this message to tell the reader that the language is correctly supported. + printf(_("If this message is in English, then your language is not supported or not correctly installed.\n")); + } +#endif + if (debug) { +#ifdef HAVE_GLOB_H + printf(_("File globbing compiled in.\n")); +#else + printf(_("File globbing NOT compiled in.\n")); +#endif + } exit(EXIT_SUCCESS); } @@ -1970,7 +2220,8 @@ void unlinkdir(const char *dir,bool contentonly) (direntp->d_name[1] == '.' && direntp->d_name[2] == '\0'))) continue; if (snprintf(dname,sizeof(dname),"%s/%s",dir,direntp->d_name)>=sizeof(dname)) { - debuga(_("directory name to delete too long: %s/%s\n"),dir,direntp->d_name); + debuga(__FILE__,__LINE__,_("Path too long: ")); + debuga_more("%s/%s\n",dir,direntp->d_name); exit(EXIT_FAILURE); } #ifdef HAVE_LSTAT @@ -1979,25 +2230,25 @@ void unlinkdir(const char *dir,bool contentonly) err=stat(dname,&st); #endif if (err) { - debuga(_("cannot stat %s\n"),dname); + debuga(__FILE__,__LINE__,_("Cannot stat \"%s\": %s\n"),dname,strerror(errno)); exit(EXIT_FAILURE); } if (S_ISREG(st.st_mode)) { if (unlink(dname)) { - debuga(_("Cannot delete \"%s\": %s\n"),dname,strerror(errno)); + debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),dname,strerror(errno)); exit(EXIT_FAILURE); } } else if (S_ISDIR(st.st_mode)) { unlinkdir(dname,0); } else { - debuga(_("unknown path type %s\n"),dname); + debuga(__FILE__,__LINE__,_("Don't know how to delete \"%s\" (not a regular file nor a directory)\n"),dname); } } closedir(dirp); if (!contentonly) { if (rmdir(dir)) { - debuga(_("Cannot delete \"%s\": %s\n"),dir,strerror(errno)); + debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),dir,strerror(errno)); exit(EXIT_FAILURE); } } @@ -2035,7 +2286,10 @@ void emptytmpdir(const char *dir) ".user_unsort", ".user_log", ".utmp", - ".ip" + ".ip", + "lastlog1", + "lastlog", + "emailrep" }; dirp=opendir(dir); @@ -2054,14 +2308,15 @@ void emptytmpdir(const char *dir) if (dlen>=elen && strcasecmp(direntp->d_name+dlen-elen,TmpExt[i])==0) break; } if (i<0) { - debuga(_("Unknown file \"%s\" found in temporary directory \"%s\". It is not one of our files. " + debuga(__FILE__,__LINE__,_("Unknown file \"%s\" found in temporary directory \"%s\". It is not one of our files. " "Please check the temporary directory you gave to sarg. Adjust the path to a safe " "directory or manually delete the content of \"%s\"\n"),direntp->d_name,dir,dir); exit(EXIT_FAILURE); } if (snprintf(dname,sizeof(dname),"%s/%s",dir,direntp->d_name)>=sizeof(dname)) { - debuga(_("directory name to delete too long: %s/%s\n"),dir,direntp->d_name); + debuga(__FILE__,__LINE__,_("Path too long: ")); + debuga_more("%s/%s\n",dir,direntp->d_name); exit(EXIT_FAILURE); } @@ -2071,13 +2326,11 @@ void emptytmpdir(const char *dir) err=stat(dname,&st); #endif if (err) { - debuga(_("cannot stat \"%s\"\n"),dname); + debuga(__FILE__,__LINE__,_("Cannot stat \"%s\": %s\n"),dname,strerror(errno)); exit(EXIT_FAILURE); } - if (S_ISDIR(st.st_mode)) { - unlinkdir(dname,0); - } else if (!S_ISREG(st.st_mode)) { - debuga(_("Unknown path type for \"%s\". Check temporary directory\n"),dname); + if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) { + debuga(__FILE__,__LINE__,_("Unknown path type for \"%s\". Check temporary directory\n"),dname); exit(EXIT_FAILURE); } } @@ -2096,14 +2349,15 @@ void emptytmpdir(const char *dir) if (dlen>=elen && strcasecmp(direntp->d_name+dlen-elen,TmpExt[i])==0) break; } if (i<0) { - debuga(_("Unknown file \"%s\" found in temporary directory \"%s\". It is not one of our files. " + debuga(__FILE__,__LINE__,_("Unknown file \"%s\" found in temporary directory \"%s\". It is not one of our files. " "Please check the temporary directory you gave to sarg. Adjust the path to a safe " "directory or manually delete the content of \"%s\"\n"),direntp->d_name,dir,dir); exit(EXIT_FAILURE); } if (snprintf(dname,sizeof(dname),"%s/%s",dir,direntp->d_name)>=sizeof(dname)) { - debuga(_("directory name to delete too long: %s/%s\n"),dir,direntp->d_name); + debuga(__FILE__,__LINE__,_("Path too long: ")); + debuga_more("%s/%s\n",dir,direntp->d_name); exit(EXIT_FAILURE); } #ifdef HAVE_LSTAT @@ -2112,16 +2366,18 @@ void emptytmpdir(const char *dir) err=stat(dname,&st); #endif if (err) { - debuga(_("cannot stat \"%s\"\n"),dname); + debuga(__FILE__,__LINE__,_("Cannot stat \"%s\": %s\n"),dname,strerror(errno)); exit(EXIT_FAILURE); } - if (S_ISREG(st.st_mode)) { + if (S_ISDIR(st.st_mode)) { + unlinkdir(dname,0); + } else if (S_ISREG(st.st_mode)) { if (unlink(dname)) { - debuga(_("Cannot delete \"%s\": %s\n"),dname,strerror(errno)); + debuga(__FILE__,__LINE__,_("Cannot delete \"%s\": %s\n"),dname,strerror(errno)); exit(EXIT_FAILURE); } } else { - debuga(_("unknown path type %s\n"),dname); + debuga(__FILE__,__LINE__,_("Don't know how to delete \"%s\" (not a regular file)\n"),dname); } } closedir(dirp);