]> git.ipfire.org Git - thirdparty/sarg.git/commitdiff
Rewrite the index tree rebuilding
authorFrederic Marchal <fmarchal@users.sourceforge.net>
Sun, 5 Oct 2014 18:36:10 +0000 (20:36 +0200)
committerFrederic Marchal <fmarchal@users.sourceforge.net>
Sun, 5 Oct 2014 18:36:10 +0000 (20:36 +0200)
When index_tree is set to "date", the reports are stored in a tree based
on their content's date. The existing code was somewhat broken.

In addition, the directory size used to be computed and displayed in the
years index file. It is now computed and displayed in the months and days
indexes.

include/defs.h
index.c
util.c

index 720eb9b1662bcd1925f9520eca01ca9ec6a51502..4fd91d7d81578b12c5982c7d8a291ab5b749b436 100755 (executable)
@@ -345,7 +345,6 @@ __attribute__((warn_unused_result)) int getword_ptr(char *orig_line,/*@out@*/cha
 long long int my_atoll (const char *nptr);
 int is_absolute(const char *path);
 int getnumlist(char *, numlist *, const int, const int);
-void name_month(char *month,int month_len);
 int conv_month(const char *month);
 const char *conv_month_name(int month);
 void buildymd(const char *dia, const char *mes, const char *ano, char *wdata,int wdata_size);
@@ -368,7 +367,6 @@ void output_html_link(FILE *fp_ou,const char *url,int maxlen);
 void debuga(const char *msg,...) __attribute__((format(printf,1,2)));
 void debugaz(const char *msg,...) __attribute__((format(printf,1,2)));
 void my_lltoa(unsigned long long int n, char *s, int ssize, int len);
-char *get_size(const char *path, const char *file);
 void url_module(const char *url, char *w2);
 void url_to_anchor(const char *url,char *anchor,int size);
 void safe_strcpy(char *dest,const char *src,int length);
diff --git a/index.c b/index.c
index 1ad06004f3e07f0cbd88ff512b3b6ec115b049fd..079b1e71d90969f14af327afa9424ee42f485345 100644 (file)
--- a/index.c
+++ b/index.c
 #include "include/conf.h"
 #include "include/defs.h"
 
+#ifdef HAVE_LSTAT
+#define MY_LSTAT lstat
+#else
+#define MY_LSTAT stat
+#endif
+
+
 static void make_date_index(void);
 static void make_file_index(void);
 static void file_index_to_date_index(const char *entry);
@@ -78,37 +85,450 @@ void make_index(void)
        }
 }
 
+/*!
+ * Get the effective size of a regular file or directory.
+ *
+ * \param statb The structure filled by lstat(2).
+ *
+ * \return The size occupied on the disk (more or less).
+ *
+ * The actual size occupied on disk by a file or a directory table is not a
+ * trivial computation. It must take into account sparse files, compression,
+ * deduplication and probably many more.
+ *
+ * Here, we assume the file takes a whole number of blocks (which is not the
+ * case of ReiserFS); the block size is constant (which is not the case of
+ * ZFS); every data block is stored in one individal block (no deduplication as
+ * is done by btrfs); data are not compressed (unlike ReiserFS and ZFS).
+ *
+ * As we are dealing with directories containing mostly text and a few
+ * compressed pictures, we don't worry about sparse files with lot of zeros
+ * that would take less blocks than the actual file size.
+ */
+static long long int get_file_size(struct stat *statb)
+{
+       long long int blocks;
+
+       //return(statb->st_size);//the size of the file content
+       //return(statb->st_blocks*512);//what is the purpose of this size?
+       if (statb->st_blksize==0) return(statb->st_size);
+       blocks=(statb->st_size+statb->st_blksize-1)/statb->st_blksize;
+       return(blocks*statb->st_blksize);//how many bytes occupied on disk
+}
+
+/*!
+ * Get the size of a directory.
+ *
+ * The size is the size of the directory content excluding the directory table.
+ * The "du" tool on Linux returns the content size including the directory
+ * table.
+ *
+ * \param path The directory whose size is computed. This is a buffer that must be
+ * big enough to contains the deepest path as directory entries are appended to
+ * the string this buffer contains.
+ * \param path_size The number of bytes available in the \a path buffer.
+ *
+ * \return The number of bytes occupied by the directory content.
+ */
+static long long int get_size(char *path,int path_size)
+{
+       int path_len;
+       DIR *dirp;
+       struct dirent *direntp;
+       struct stat statb;
+       int name_len;
+       long long int total_size=0;
+       char *dir_list=NULL;
+       int dir_filled=0;
+       int dir_allocated=0;
+
+       path_len=strlen(path);
+       if (path_len+2>=path_size) {
+               debuga(_("Directory entry \"%s\" too long\n"),path);
+               exit(EXIT_FAILURE);
+       }
+       if ((dirp=opendir(path))==NULL) {
+               debuga(_("Cannot open directory %s: %s\n"),path,strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       path[path_len++]='/';
+       while ((direntp=readdir(dirp))!=NULL) {
+               if (direntp->d_name[0]=='.' && (direntp->d_name[1]=='\0' || (direntp->d_name[1]=='.' && direntp->d_name[2]=='\0'))) continue;
+               name_len=strlen(direntp->d_name);
+               if (path_len+name_len+1>=path_size) {
+                       debuga(_("Directory entry \"%s%s\" too long\n"),path,direntp->d_name);
+                       exit(EXIT_FAILURE);
+               }
+               strcpy(path+path_len,direntp->d_name);
+               if (MY_LSTAT(path,&statb) == -1) {
+                       debuga(_("Failed to get the file statistics of %s: %s\n"),path,strerror(errno));
+                       continue;
+               }
+               if (S_ISDIR(statb.st_mode))
+               {
+                       if (!dir_list || dir_filled+name_len>=dir_allocated)
+                       {
+                               int size=3*(name_len+1);//make room for three file names like this one
+                               if (size<256) size=256;
+                               dir_allocated+=size;
+                               dir_list=realloc(dir_list,dir_allocated);
+                               if (!dir_list) {
+                                       debuga(_("Not enough memory to recurse into subdirectory\n"));
+                                       exit(EXIT_FAILURE);
+                               }
+                       }
+                       strcpy(dir_list+dir_filled,direntp->d_name);
+                       dir_filled+=name_len+1;
+                       total_size+=get_file_size(&statb);
+               }
+               else if (S_ISREG(statb.st_mode))
+               {
+                       total_size+=get_file_size(&statb);
+               }
+       }
+       closedir(dirp);
+
+       if (dir_list)
+       {
+               int start=0;
+
+               while (start<dir_filled)
+               {
+                       name_len=strlen(dir_list+start);
+                       strcpy(path+path_len,dir_list+start);
+                       total_size+=get_size(path,path_size);
+                       start+=name_len+1;
+               }
+               free(dir_list);
+       }
+
+       path[path_len-1]='\0';//restore original string
+       return (total_size);
+}
+
+/*!
+ * Rebuild the html index file for a day when the reports are grouped in a date tree.
+ *
+ * \param monthdir The buffer containing the path where the html index file must be rebuild.
+ * The buffer must be big enough to contain the deepest path in that directory as the buffer is
+ * used to concatenate the directory entries.
+ * \param monthdir_size The size, in byte, of the \a monthdir buffer.
+ * \param order A postive number to sort the index file in positive order. A negative value sort it
+ * in decreasing order.
+ * \param yearnum The string naming the year in the date tree.
+ * \param monthnum The string naming the month in the date tree.
+ *
+ * \return The approximate size occupied by the directory.
+ */
+static long long int make_date_index_day(char *monthdir,int monthdir_size,int order,const char *yearnum,const char *monthnum)
+{
+       int monthdir_len;
+       int ndays;
+       DIR *dirp3;
+       struct dirent *direntp;
+       struct stat statb;
+       int i;
+       int daysort[31*31];
+       int d1, d2, day;
+       FILE *fp_ou;
+       char title[80];
+       char daynum[10];
+       int d;
+       long long int total_size=0;
+       long long int sub_size;
+       int name_len;
+
+       ndays=0;
+       if ((dirp3 = opendir(monthdir)) == NULL) {
+               debuga(_("Failed to open directory %s - %s\n"),monthdir,strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       monthdir_len=strlen(monthdir);
+       if (monthdir_len+strlen(INDEX_HTML_FILE)+2>=monthdir_size) {
+               debuga(_("Directory path too long: %s/%s\n"),monthdir,INDEX_HTML_FILE);
+               exit(EXIT_FAILURE);
+       }
+       monthdir[monthdir_len++]='/';
+       while ((direntp = readdir( dirp3 )) != NULL) {
+               if (direntp->d_name[0]=='.' && (direntp->d_name[1]=='\0' || (direntp->d_name[1]=='.' && direntp->d_name[2]=='\0'))) continue;
+               name_len=strlen(direntp->d_name);
+               if (monthdir_len+name_len+1>=monthdir_size) {
+                       debuga(_("Directory entry \"%s%s\" too long\n"),monthdir,direntp->d_name);
+                       exit(EXIT_FAILURE);
+               }
+               strcpy(monthdir+monthdir_len,direntp->d_name);
+               if (MY_LSTAT(monthdir,&statb) == -1) {
+                       debuga(_("Failed to get the file statistics of %s: %s\n"),monthdir,strerror(errno));
+                       continue;
+               }
+               if (S_ISDIR(statb.st_mode))
+               {
+                       if(!isdigit(direntp->d_name[0]) && !isdigit(direntp->d_name[1])) continue;
+                       i=-1;
+                       if (sscanf(direntp->d_name,"%d%n",&d1,&i)!=1 || d1<1 || d1>31 || i<0) continue;
+                       if (direntp->d_name[i]=='-') {
+                               if (sscanf(direntp->d_name+i+1,"%d",&d2)!=1 || d2<1 || d2>31) continue;
+                       } else if (direntp->d_name[i]!='\0') {
+                               continue;
+                       } else {
+                               d2=0;
+                       }
+                       if (ndays>=sizeof(daysort)/sizeof(daysort[0])) {
+                               debuga(_("Too many day directories in %s\nSupernumerary entries are ignored\n"),monthdir);
+                               break;
+                       }
+                       day=(d1 << 5) | d2;
+                       for (i=ndays ; i>0 &&  day<daysort[i-1] ; i--) {
+                               daysort[i]=daysort[i-1];
+                       }
+                       daysort[i]=day;
+                       ndays++;
+                       total_size+=get_file_size(&statb);
+               }
+               else if (S_ISREG(statb.st_mode))
+               {
+                       total_size+=get_file_size(&statb);
+               }
+       }
+       closedir(dirp3);
+
+       strcpy(monthdir+monthdir_len,INDEX_HTML_FILE);
+       if((fp_ou=fopen(monthdir,"w"))==NULL) {
+               debuga(_("(index) Cannot open file %s: %s\n"),monthdir,strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       snprintf(title,sizeof(title),ngettext("SARG: report for %s/%s","SARG: reports for %s/%s",ndays),yearnum,monthnum);
+       write_html_header(fp_ou,2,title,HTML_JS_NONE);
+       close_html_header(fp_ou);
+       fputs("<div class=\"index\"><table cellpadding=\"1\" cellspacing=\"2\">\n<tr><td></td><td></td></tr>\n",fp_ou);
+       fprintf(fp_ou,"<tr><th class=\"header_l\">%s/%s/%s</th>",_("YEAR"),_("MONTH"),_("DAYS"));
+       if (IndexFields & INDEXFIELDS_DIRSIZE)
+               fprintf(fp_ou,"<th class=\"header_l\">%s</th>",_("SIZE"));
+       fputs("</tr>\n",fp_ou);
+       for (d=0 ; d<ndays ; d++) {
+               if (order>0)
+                       day=daysort[d];
+               else
+                       day=daysort[ndays-1-d];
+               d1=(day >> 5) & 0x1F;
+               if ((day & 0x1F) != 0) {
+                       d2=day & 0x1F;
+                       sprintf(daynum,"%02d-%02d",d1,d2);
+               } else {
+                       sprintf(daynum,"%02d",d1);
+               }
+               strcpy(monthdir+monthdir_len,daynum);
+               sub_size=get_size(monthdir,monthdir_size);
+
+               fprintf(fp_ou,"<tr><td class=\"data2\"><a href=\"%s/%s\">%s %s %s</a></td>",daynum,INDEX_HTML_FILE,yearnum,monthnum,daynum);
+               if (IndexFields & INDEXFIELDS_DIRSIZE)
+               {
+                       char size_str[40];
+
+                       strncpy(size_str,fixnum(sub_size,1),sizeof(size_str)-1);
+                       size_str[sizeof(size_str)-1]='\0';
+                       fprintf(fp_ou,"<td class=\"data2\">%s</td>",size_str);
+               }
+               fputs("</tr>\n",fp_ou);
+               total_size+=sub_size;
+       }
+       fputs("</table></div>\n",fp_ou);
+       monthdir[monthdir_len-1]='\0';
+       if (write_html_trailer(fp_ou)<0)
+               debuga(_("Write error in the index %s/%s\n"),monthdir,INDEX_HTML_FILE);
+       if (fclose(fp_ou)==EOF) {
+               debuga(_("Write error in %s/%s: %s\n"),monthdir,INDEX_HTML_FILE,strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       return(total_size);
+}
+
+/*!
+ * Get the name of a month based on its number.
+ *
+ * \param month The month number starting from one.
+ * \param month_name The buffer to store the month name.
+ * \param month_size The size of the \a month_name buffer.
+ */
+static void name_month(int month,char *month_name,int month_size)
+{
+       const char *m[12]={N_("January"),N_("February"),N_("March"),N_("April"),N_("May"),N_("June"),N_("July"),
+                                          N_("August"),N_("September"),N_("October"),N_("November"),N_("December")};
+
+       if (month<1 || month>12) {
+               debuga(_("The internal list of month names is invalid. Please report this bug to the translator.\n"));
+               exit(EXIT_FAILURE);
+       }
+       strncpy(month_name,_(m[month-1]),month_size-1);
+       month_name[month_size-1]='\0';
+}
+
+/*!
+ * Rebuild the html index file for a month when the reports are grouped in a date tree.
+ *
+ * \param yeardir The buffer containing the path where the html index file must be rebuild.
+ * The buffer must be big enough to contain the deepest path in that directory as the buffer is
+ * used to concatenate the directory entries.
+ * \param yeardir_size The size, in byte, of the \a yeardir buffer.
+ * \param order A postive number to sort the index file in positive order. A negative value sort it
+ * in decreasing order.
+ * \param yearnum The string naming the year in the date tree.
+ *
+ * \return The approximate size occupied by the directory.
+ */
+static long long int make_date_index_month(char *yeardir,int yeardir_size,int order,const char *yearnum)
+{
+       int yeardir_len;
+       int nmonths;
+       DIR *dirp2;
+       struct dirent *direntp;
+       struct stat statb;
+       int i;
+       int monthsort[144];
+       int m1, m2, month;
+       FILE *fp_ou;
+       char title[80];
+       char monthname1[9], monthname2[9];
+       char nmonth[30];
+       char monthnum[10];
+       int m;
+       long long int total_size=0;
+       long long int sub_size;
+       int name_len;
+
+       nmonths=0;
+       if ((dirp2 = opendir(yeardir)) == NULL) {
+               debuga(_("Failed to open directory %s - %s\n"),yeardir,strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       yeardir_len=strlen(yeardir);
+       if (yeardir_len+strlen(INDEX_HTML_FILE)+2>=yeardir_size) {
+               debuga(_("Directory path too long: %s/%s\n"),yeardir,INDEX_HTML_FILE);
+               exit(EXIT_FAILURE);
+       }
+       yeardir[yeardir_len++]='/';
+       while ((direntp = readdir( dirp2 )) != NULL) {
+               if (direntp->d_name[0]=='.' && (direntp->d_name[1]=='\0' || (direntp->d_name[1]=='.' && direntp->d_name[2]=='\0'))) continue;
+               name_len=strlen(direntp->d_name);
+               if (yeardir_len+name_len+1>=yeardir_size) {
+                       debuga(_("Directory entry \"%s%s\" too long\n"),yeardir,direntp->d_name);
+                       exit(EXIT_FAILURE);
+               }
+               strcpy(yeardir+yeardir_len,direntp->d_name);
+               if (MY_LSTAT(yeardir,&statb) == -1) {
+                       debuga(_("Failed to get the file statistics of %s: %s\n"),yeardir,strerror(errno));
+                       continue;
+               }
+               if (S_ISDIR(statb.st_mode))
+               {
+                       if(!isdigit(direntp->d_name[0]) || !isdigit(direntp->d_name[1])) continue;
+                       i=-1;
+                       if (sscanf(direntp->d_name,"%d%n",&m1,&i)!=1 || m1<1 || m1>12 || i<0) continue;
+                       if (direntp->d_name[i]=='-') {
+                               if (sscanf(direntp->d_name+i+1,"%d",&m2)!=1 || m2<1 || m2>12) continue;
+                       } else if (direntp->d_name[i]!='\0') {
+                               continue;
+                       } else {
+                               m2=0;
+                       }
+                       if (nmonths>=sizeof(monthsort)/sizeof(monthsort[0])) {
+                               debuga(_("Too many month directories in %s\nSupernumerary entries are ignored\n"),yeardir);
+                               break;
+                       }
+                       month=(m1<<4) | m2;
+                       for (i=nmonths ; i>0 &&  month<monthsort[i-1] ; i--) {
+                               monthsort[i]=monthsort[i-1];
+                       }
+                       monthsort[i]=month;
+                       nmonths++;
+                       total_size+=get_file_size(&statb);
+               }
+               else if (S_ISREG(statb.st_mode))
+               {
+                       total_size+=get_file_size(&statb);
+               }
+       }
+       closedir(dirp2);
+
+       strcpy(yeardir+yeardir_len,INDEX_HTML_FILE);
+       if((fp_ou=fopen(yeardir,"w"))==NULL) {
+               debuga(_("(index) Cannot open file %s: %s\n"),yeardir,strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       snprintf(title,sizeof(title),ngettext("SARG: report for %s","SARG: reports for %s",nmonths),yearnum);
+       write_html_header(fp_ou,1,title,HTML_JS_NONE);
+       close_html_header(fp_ou);
+       fputs("<div class=\"index\"><table cellpadding=\"1\" cellspacing=\"2\">\n<tr><td></td><td></td></tr>\n",fp_ou);
+       fprintf(fp_ou,"<tr><th class=\"header_l\">%s/%s</th>",_("YEAR"),_("MONTH"));
+       if (IndexFields & INDEXFIELDS_DIRSIZE)
+               fprintf(fp_ou,"<th class=\"header_l\">%s</th>",_("SIZE"));
+       fputs("</tr>\n",fp_ou);
+       for (m=0 ; m<nmonths ; m++) {
+               if (order>0)
+                       month=monthsort[m];
+               else
+                       month=monthsort[nmonths-1-m];
+               m1=(month >> 4) & 0x0F;
+               if ((month & 0x0F) != 0) {
+                       m2=month & 0x0F;
+                       sprintf(monthnum,"%02d-%02d",m1,m2);
+                       name_month(m1,monthname1,sizeof(monthname1));
+                       name_month(m2,monthname2,sizeof(monthname2));
+                       sprintf(nmonth,"%s-%s",monthname1,monthname2);
+               } else {
+                       sprintf(monthnum,"%02d",m1);
+                       name_month(m1,nmonth,sizeof(nmonth));
+               }
+               if (yeardir_len+strlen(monthnum)+1>=yeardir_size) {
+                       yeardir[yeardir_len]='\0';
+                       debuga(_("Directory path too long: %s%s\n"),yeardir,monthnum);
+                       exit(EXIT_FAILURE);
+               }
+               strcpy(yeardir+yeardir_len,monthnum);
+               sub_size=make_date_index_day(yeardir,yeardir_size,order,yearnum,nmonth);
+
+               fprintf(fp_ou,"<tr><td class=\"data2\"><a href=\"%s/%s\">%s %s</a></td>",monthnum,INDEX_HTML_FILE,yearnum,nmonth);
+               if (IndexFields & INDEXFIELDS_DIRSIZE)
+               {
+                       char size_str[40];
+
+                       strncpy(size_str,fixnum(sub_size,1),sizeof(size_str)-1);
+                       size_str[sizeof(size_str)-1]='\0';
+                       fprintf(fp_ou,"<td class=\"data2\">%s</td>",size_str);
+               }
+               fputs("</tr>\n",fp_ou);
+               total_size+=sub_size;
+       }
+       fputs("</table></div>\n",fp_ou);
+       yeardir[yeardir_len-1]='\0';
+       if (write_html_trailer(fp_ou)<0) {
+               debuga(_("Write error in the index %s/%s\n"),yeardir,INDEX_HTML_FILE);
+       }
+       if (fclose(fp_ou)==EOF) {
+               debuga(_("Write error in %s/%s: %s\n"),yeardir,INDEX_HTML_FILE,strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       return(total_size);
+}
+
+/*!
+ * Rebuild a date index tree in the output directory.
+ */
 static void make_date_index(void)
 {
-       FILE *fp_ou, *fp_ou2, *fp_ou3;
-       DIR *dirp, *dirp2, *dirp3;
+       FILE *fp_ou;
+       DIR *dirp;
        struct dirent *direntp;
-       struct dirent *direntp2;
-       struct dirent *direntp3;
        char yearindex[MAXLEN];
        char yeardir[MAXLEN];
        char yearnum[10];
-       char monthindex[MAXLEN];
-       char monthdir[MAXLEN];
-       char monthname1[9], monthname2[9];
-       char nmonth[30];
-       char monthnum[10];
-       char dayindex[MAXLEN];
-       char daynum[10];
-       char title[80];
        int yearsort[150];
        int nyears;
        int year;
-       int monthsort[144];
-       int nmonths;
-       int m1, m2, month;
-       int daysort[31*31];
-       int ndays;
-       int d1, d2, day;
-       int i, y, m, d;
+       int i, y;
        int order;
-
-       sprintf(yearindex,"%s"INDEX_HTML_FILE,outdir);
+       int yeardirlen;
+       long long int total_size;
 
        nyears=0;
        if ((dirp = opendir(outdir)) == NULL) {
@@ -116,9 +536,20 @@ static void make_date_index(void)
                exit(EXIT_FAILURE);
        }
        while ((direntp = readdir( dirp )) != NULL) {
-               if(strlen(direntp->d_name) > 4 || !isdigit(direntp->d_name[0]) || !isdigit(direntp->d_name[1]) ||
+               if (!isdigit(direntp->d_name[0]) || !isdigit(direntp->d_name[1]) ||
                   !isdigit(direntp->d_name[2]) || !isdigit(direntp->d_name[3])) continue;
-               year=atoi(direntp->d_name);
+               year=atoi(direntp->d_name) << 10;
+               if (direntp->d_name[4]=='-')
+               {
+                       if (!isdigit(direntp->d_name[5]) || !isdigit(direntp->d_name[6]) ||
+                          !isdigit(direntp->d_name[7]) || !isdigit(direntp->d_name[8])) continue;
+                       if (direntp->d_name[9]) continue;
+                       year|=atoi(direntp->d_name+5);
+               }
+               else
+               {
+                       if (direntp->d_name[4]) continue;
+               }
                if (nyears>=sizeof(yearsort)/sizeof(yearsort[0])) {
                        /*
                        If too many years are listed in the directory, we ignore the earliest years. The yearsort array
@@ -142,6 +573,10 @@ static void make_date_index(void)
 
        order=(strcmp(IndexSortOrder,"A") == 0) ? 1 : -1;
 
+       if (snprintf(yearindex,sizeof(yearindex),"%s"INDEX_HTML_FILE,outdir)>=sizeof(yearindex)) {
+               debuga(_("Resulting index file name too long: %s/%s"),outdir,INDEX_HTML_FILE);
+               exit(EXIT_FAILURE);
+       }
        if((fp_ou=fopen(yearindex,"w"))==NULL) {
                debuga(_("(index) Cannot open file %s: %s\n"),yearindex,strerror(errno));
                exit(EXIT_FAILURE);
@@ -153,146 +588,36 @@ static void make_date_index(void)
        if (IndexFields & INDEXFIELDS_DIRSIZE)
                fprintf(fp_ou,"<th class=\"header_l\">%s</th>",_("SIZE"));
        fputs("</tr>\n",fp_ou);
+
+       yeardirlen=strlen(outdir);
+       if (yeardirlen>=sizeof(yeardir)) {
+               debuga(_("Output directory too long: %s"),outdir);
+               exit(EXIT_FAILURE);
+       }
+       strcpy(yeardir,outdir);
+
        for (y=0 ; y<nyears ; y++) {
                if (order>0)
                        year=yearsort[y];
                else
                        year=yearsort[nyears-1-y];
-               sprintf(yearnum,"%04d",year);
+               if ((year & 0x3FF)==0)
+                       sprintf(yearnum,"%04d",year>>10);
+               else
+                       sprintf(yearnum,"%04d-%04d",year>>10,year & 0x3FF);
+               strcpy(yeardir+yeardirlen,yearnum);
+               total_size=make_date_index_month(yeardir,sizeof(yeardir),order,yearnum);
+
                fprintf(fp_ou,"<tr><td class=\"data2\"><a href=\"%s/%s\">%s</a></td>",yearnum,INDEX_HTML_FILE,yearnum);
                if (IndexFields & INDEXFIELDS_DIRSIZE)
-                       fprintf(fp_ou,"<td class=\"data2\">%s</td>",get_size(outdir,yearnum));
-               fputs("</tr>\n",fp_ou);
-               sprintf(yeardir,"%s%s",outdir,yearnum);
-               // Year dir
-               nmonths=0;
-               if ((dirp2 = opendir(yeardir)) == NULL) {
-                       debuga(_("Failed to open directory %s - %s\n"),yeardir,strerror(errno));
-                       exit(EXIT_FAILURE);
-               }
-               while ((direntp2 = readdir( dirp2 )) != NULL) {
-                       if(!isdigit(direntp2->d_name[0]) || !isdigit(direntp2->d_name[1])) continue;
-                       i=-1;
-                       if (sscanf(direntp2->d_name,"%d%n",&m1,&i)!=1 || m1<=0 || m1>12 || i<0) continue;
-                       if (direntp2->d_name[i]=='-') {
-                               if (sscanf(direntp2->d_name+i+1,"%d",&m2)!=1 || m2<m1 || m2>12) continue;
-                       } else if (direntp2->d_name[i]!='\0') {
-                               continue;
-                       } else {
-                               m2=0;
-                       }
-                       if (nmonths>=sizeof(monthsort)/sizeof(monthsort[0])) {
-                               debuga(_("Too many month directories in %s\nSupernumerary entries are ignored\n"),yeardir);
-                               break;
-                       }
-                       month=m1*16+m2;
-                       for (i=nmonths ; i>0 &&  month<monthsort[i-1] ; i--) {
-                               monthsort[i]=monthsort[i-1];
-                       }
-                       monthsort[i]=month;
-                       nmonths++;
-               }
-               closedir(dirp2);
-               sprintf(monthindex,"%s/"INDEX_HTML_FILE,yeardir);
-               if((fp_ou2=fopen(monthindex,"w"))==NULL) {
-                       debuga(_("(index) Cannot open file %s: %s\n"),monthindex,strerror(errno));
-                       exit(EXIT_FAILURE);
-               }
-               snprintf(title,sizeof(title),ngettext("SARG: report for %04d","SARG: reports for %04d",nmonths),year);
-               write_html_header(fp_ou2,1,title,HTML_JS_NONE);
-               close_html_header(fp_ou2);
-               fputs("<div class=\"index\"><table cellpadding=\"1\" cellspacing=\"2\">\n<tr><td></td><td></td></tr>\n",fp_ou2);
-               fprintf(fp_ou2,"<tr><th class=\"header_l\">%s/%s</th></tr>\n",_("YEAR"),_("MONTH"));
-               for (m=0 ; m<nmonths ; m++) {
-                       if (order>0)
-                               month=monthsort[m];
-                       else
-                               month=monthsort[nmonths-1-m];
-                       m1=month / 16;
-                       if(month % 16 != 0) {
-                               m2=month % 16;
-                               sprintf(monthnum,"%02d-%02d",m1,m2);
-                               sprintf(monthname1,"%02d",m1);
-                               sprintf(monthname2,"%02d",m2);
-                               name_month(monthname1,sizeof(monthname1));
-                               name_month(monthname2,sizeof(monthname2));
-                               sprintf(nmonth,"%s-%s",monthname1,monthname2);
-                       } else {
-                               sprintf(nmonth,"%02d",m1);
-                               sprintf(monthnum,"%02d",m1);
-                               name_month(nmonth,sizeof(nmonth));
-                       }
-                       fprintf(fp_ou2,"<tr><td class=\"data2\"><a href=\"%s/%s\">%s %s</a></td></tr>\n",monthnum,INDEX_HTML_FILE,yearnum,nmonth);
+               {
+                       char size_str[40];
 
-                       sprintf(monthdir,"%s/%s",yeardir,monthnum);
-                       // month dir
-                       ndays=0;
-                       if ((dirp3 = opendir(monthdir)) == NULL) {
-                               debuga(_("Failed to open directory %s - %s\n"),monthdir,strerror(errno));
-                               exit(EXIT_FAILURE);
-                       }
-                       while ((direntp3 = readdir( dirp3 )) != NULL) {
-                               if(!isdigit(direntp3->d_name[0]) && !isdigit(direntp3->d_name[1])) continue;
-                               i=-1;
-                               if (sscanf(direntp3->d_name,"%d%n",&d1,&i)!=1 || d1<=0 || d1>31 || i<0) continue;
-                               if (direntp3->d_name[i]=='-') {
-                                       if (sscanf(direntp3->d_name+i+1,"%d",&d2)!=1 || d2<d1 || d2>31) continue;
-                               } else if (direntp3->d_name[i]!='\0') {
-                                       continue;
-                               } else {
-                                       d2=0;
-                               }
-                               if (ndays>=sizeof(daysort)/sizeof(daysort[0])) {
-                                       debuga(_("Too many day directories in %s\nSupernumerary entries are ignored\n"),monthdir);
-                                       break;
-                               }
-                               day=d1*32+d2;
-                               for (i=ndays ; i>0 &&  day<daysort[i-1] ; i--) {
-                                       daysort[i]=daysort[i-1];
-                               }
-                               daysort[i]=day;
-                               ndays++;
-                       }
-                       closedir(dirp3);
-                       sprintf(dayindex,"%s/"INDEX_HTML_FILE,monthdir);
-                       if((fp_ou3=fopen(dayindex,"w"))==NULL) {
-                               debuga(_("(index) Cannot open file %s: %s\n"),dayindex,strerror(errno));
-                               exit(EXIT_FAILURE);
-                       }
-                       snprintf(title,sizeof(title),ngettext("SARG: report for %04d/%02d","SARG: reports for %04d/%02d",ndays),year,month);
-                       write_html_header(fp_ou3,2,title,HTML_JS_NONE);
-                       close_html_header(fp_ou3);
-                       fputs("<div class=\"index\"><table cellpadding=\"1\" cellspacing=\"2\">\n<tr><td></td><td></td></tr>\n",fp_ou3);
-                       fprintf(fp_ou3,"<tr><th class=\"header_l\">%s/%s/%s</th></tr>\n",_("YEAR"),_("MONTH"),_("DAYS"));
-                       for (d=0 ; d<ndays ; d++) {
-                               if (order>0)
-                                       day=daysort[d];
-                               else
-                                       day=daysort[ndays-1-d];
-                               d1=day / 32;
-                               if(day % 32 != 0) {
-                                       d2=day % 32;
-                                       sprintf(daynum,"%02d-%02d",d1,d2);
-                               } else {
-                                       sprintf(daynum,"%02d",d1);
-                               }
-                               fprintf(fp_ou3,"<tr><td class=\"data2\"><a href=\"%s/%s\">%s %s %s</a></td></tr>\n",daynum,INDEX_HTML_FILE,yearnum,nmonth,daynum);
-                       }
-                       fputs("</table></div>\n",fp_ou3);
-                       if (write_html_trailer(fp_ou3)<0)
-                               debuga(_("Write error in the index %s\n"),dayindex);
-                       if (fclose(fp_ou3)==EOF) {
-                               debuga(_("Write error in %s: %s\n"),dayindex,strerror(errno));
-                               exit(EXIT_FAILURE);
-                       }
-               }
-               fputs("</table></div>\n",fp_ou2);
-               if (write_html_trailer(fp_ou2)<0)
-                       debuga(_("Write error in the index %s\n"),monthindex);
-               if (fclose(fp_ou2)==EOF) {
-                       debuga(_("Write error in %s: %s\n"),monthindex,strerror(errno));
-                       exit(EXIT_FAILURE);
+                       strncpy(size_str,fixnum(total_size,1),sizeof(size_str)-1);
+                       size_str[sizeof(size_str)-1]='\0';
+                       fprintf(fp_ou,"<td class=\"data2\">%s</td>",size_str);
                }
+               fputs("</tr>\n",fp_ou);
        }
 
        fputs("</table></div>\n",fp_ou);
diff --git a/util.c b/util.c
index cf44007b38865a36732a637d9347fedd18453303..0511b3565d7571f6ed06897bbda7ce88deb8868c 100644 (file)
--- a/util.c
+++ b/util.c
@@ -527,29 +527,6 @@ const char *conv_month_name(int month)
        return(mtab1[month-1]);
 }
 
-
-void name_month(char *month,int month_len)
-{
-       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);
-
-       for(x=0; x<z; x++)
-               if (getword_multisep(w,sizeof(w),&gwarea,',')<0) {
-                       debuga(_("The internal list of month names is invalid. Please report this bug to the translator.\n"));
-                       exit(EXIT_FAILURE);
-               }
-       if (getword_multisep(month,month_len,&gwarea,',')<0) {
-               debuga(_("The internal list of month names is invalid. Please report this bug to the translator.\n"));
-               exit(EXIT_FAILURE);
-       }
-}
-
-
 /*!
 Write a debug message to stderr. The message is prefixed by "SARG:" to identify its origin.
 
@@ -1892,37 +1869,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];