// Filename: fileutil.C // Contents: a files area utility program // Author: Greg Shaw // Created: 8/24/93 /* This file is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. In addition to the permissions in the GNU General Public License, the Free Software Foundation gives you unlimited permission to link the compiled version of this file with other programs, and to distribute those programs without any restriction coming from the use of this file. (The General Public License restrictions do apply in other respects; for example, they cover modification of the file, and distribution when not linked into another program.) This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef _FILEUTIL_C_ #define _FILEUTIL_C_ #include "bbshdr.h" #include "fileutil.h" User user; // defined here for extern references elsewhere moncon mon_obj; // monitor connection object (not used) // Method: constructor // Purpose: initialize the list // Input: none // Output: none // Author: Greg Shaw // Created: 8/24/93 fileutil::fileutil() { numrecs = 0; }; // Method: delete_missing // Purpose: scan all files sections to delete all missing files // Input: sname - long name of file section // Output: stdout - list of deleted files // Author: Greg Shaw // Created: 9/2/93 int fileutil::delete_missing(char *sname,char *secname) { FInfo *rec; int deleted; int offset; FILE *recfile; FILE *outfile; char fname[MAX_FILENAMELENGTH+1]; char tmpstr[255]; char c; char line[150]; deleted = 0; sprintf(tmpstr,"%s/filehdr/%s",getenv("BBSDIR"),secname); if (recfile = bopen(tmpstr,"r"), recfile == NULL) { sprintf(tmpstr,"fileutil: Unable to open %s",secname); ap_log(tmpstr); return(-1); } sprintf(tmpstr,"%s/filehdr/%s.new",getenv("BBSDIR"),secname); if (outfile = bopen(tmpstr,"w"), outfile == NULL) { sprintf(tmpstr,"fileutil: Unable to open %s.new",secname); ap_log(tmpstr); return(-1); } while (!feof(recfile)) { offset = 0; while (c = fgetc(recfile), c != '\n' && c != '\r' && !feof(recfile)) line[offset++] = c; line[offset] = 0; if (line[0] == '[' && line[1] == 'A') { sscanf(&line[2],"%*s %*d %s",fname); if (rec = list_obj.find(fname), rec != NULL && rec->avail != 'Y' || rec->size == 0) { // delete next 5 more lines deleted++; offset = 0; while (offset < 5 && !feof(recfile)) { while (c = fgetc(recfile), c != '\n' && c != '\r' && !feof(recfile)); offset++; } } else fprintf(outfile,"%s\n",line); } else fprintf(outfile,"%s\n",line); } bclose(outfile); bclose(recfile); if (deleted) // some deleted? { // now move things back to where they should be sprintf(tmpstr,"%s/filehdr/%s",getenv("BBSDIR"),secname); sprintf(line,"%s/filehdr/%s.old",getenv("BBSDIR"),secname); rename(tmpstr,line); sprintf(line,"%s/filehdr/%s.new",getenv("BBSDIR"),secname); sprintf(tmpstr,"%s/filehdr/%s",getenv("BBSDIR"),secname); rename(line,tmpstr); } else { sprintf(tmpstr,"%s/filehdr/%s.new",getenv("BBSDIR"),secname); remove(tmpstr); } printf("%-25.25s %6d\n",sname,deleted); return(0); }; // Method: newfiles // Purpose: scan all files sections to build a 'new files' list. // Input: section - name of section to build the 'new' list for // fname - the file name (+path) for the output file // Output: a file that contains the new files list // Author: Greg Shaw // Created: 8/24/93 int fileutil::newfiles(char *section, FILE *outfile) { FInfo *rec; char datestr[12]; struct tm *tmrec; time_t now; time(&now); list_obj.top(); // top of list while (rec = list_obj.next(), rec != NULL) { if (now - rec->date < (DAYS*24*60*60)) { tmrec = localtime(&rec->date); strftime(datestr,11,"%x",tmrec); fprintf(outfile,"%-14.14s %-25.25s %s %-8.8s %2d\n",rec->name, section,datestr,rec->uploader,rec->numdls); } } return(0); }; // Method: most // Purpose: scan the files section for the most popular files. Compare // against existing list and add as appropriate // Input: section - name of section to build the 'most' list for // fname - the file name (+path) for the output file // Output: a file that contains the most popular files // Author: Greg Shaw // Created: 8/24/93 int fileutil::most(char *section) { FInfo *rec; int num; int x; struct stat fistat; // file status record char tmpstr[255]; list_obj.top(); // top of list while (rec = list_obj.next(), rec != NULL) { sprintf(tmpstr,"%s/files/%s/%s",getenv("BBSDIR"),dn_path,rec->name); if (stat(tmpstr,&fistat) == 0 && S_ISREG (fistat.st_mode)) { rec->size = fistat.st_size; rec->date = fistat.st_ctime; rec->avail = 'Y'; } if (rec->numdls > 0) { num = -1; for (x=0; xnumdls > recs[x].numdls) { num = x; // found where we need to put guy x = numrecs; } } if (num != -1 ) // found where we need to put him { // move everybody down for (x=numrecs-2; x >= num; --x) { memcpy(&recs[x+1], &recs[x], sizeof(FInfo)); strcpy(sec[x+1], sec[x]); } memcpy(&recs[num], rec, sizeof(FInfo)); strcpy(sec[num], section); } else if (x < MAX_RECS) // hit end before found lesser one { memcpy(&recs[numrecs],rec,sizeof(FInfo)); strcpy(sec[numrecs], section); numrecs++; } } } return(0); }; // Method: update // Purpose: update the section passed in // - check for new files added to directory // - delete files with zero length in description // Input: section - name of section to update // Output: a file that contains the most popular files // Author: Greg Shaw // Created: 8/24/93 int fileutil::update(char *section) { FILE *outfile; // output file DIR *fdir; // directory file descriptor FInfo *rec; struct dirent *dentry; // directory entry struct stat fistat; // file status record time_t now; // date of file added (today) char bbsdir[255]; // bbs directory char tmpstr[255]; // tmpstr int newfiles; // new files in section int missing; // missing files in section int deleted; // missing files in section int totfiles; // total files in section unsigned long totsize; // total size of section time(&now); newfiles = deleted = missing = totfiles = 0; totsize = 0; strcpy(bbsdir,getenv("BBSDIR")); // not checking error strcpy(tmpstr,bbsdir); strcat(tmpstr,"/filehdr/"); // tack on files header strcat(tmpstr,section); if (outfile = bopen(tmpstr,"a"), outfile == NULL) { printf("fileutil: Unable to open files section header %s",section); return(0); } strcpy(tmpstr,bbsdir); strcat(tmpstr,"/files/"); strcat(tmpstr,dn_path); if (fdir = opendir(tmpstr), fdir == NULL) { printf("fileutil: Unable to open directory %s for reading.\n",tmpstr); bclose(outfile); exit(0); } // ok. output file is open. directory is open. doit. while (dentry = readdir(fdir), dentry != NULL) { sprintf(tmpstr,"%s/files/%s/%s",bbsdir,dn_path,dentry->d_name); if (stat(tmpstr,&fistat) == 0 && S_ISREG(fistat.st_mode)) { // not found, add to area if (rec = list_obj.find(dentry->d_name), rec == NULL) { newfiles++; totsize += fistat.st_size/1024; fprintf(outfile,"[A sysop 0 %s ]\n",dentry->d_name, fistat.st_size,fistat.st_ctime); fprintf(outfile,"[B ]\n"); fprintf(outfile,"[C ]\n"); fprintf(outfile,"[D ]\n"); fprintf(outfile,"[E ]\n"); fprintf(outfile,"[F ]\n"); } } } closedir(fdir); bclose(outfile); // Ok. Got new files added to section. Now delete no-good files list_obj.top(); // start at top while (rec = list_obj.next(), rec != NULL) { if (rec != NULL && rec->size == 0) // file size 0? Kill! { deleted++; sprintf(tmpstr,"%s/files/%s/%s",bbsdir,dn_path,rec->name); remove(tmpstr); } } // now go through section file to delete record descriptions // now check for missing files list_obj.top(); // start at top while (rec = list_obj.next(), rec != NULL) { sprintf(tmpstr,"%s/files/%s/%s",getenv("BBSDIR"),dn_path,rec->name); if (stat(tmpstr,&fistat) == 0 && S_ISREG (fistat.st_mode)) { rec->size = fistat.st_size; rec->date = fistat.st_ctime; rec->avail = 'Y'; totsize += rec->size/1024; totfiles++; } } // now add statistics to file totfiles += newfiles; totfiles -= deleted; printf("%-25.25s %6ld %5d %3d %3d %3d\n",section,totsize, totfiles,missing,newfiles,deleted); sprintf(tmpstr,"%s/filehdr/%s",bbsdir,section); chmod(tmpstr,0775); return(0); }; // Method: cycle_sections // Purpose: scan all files sections and do a command on each in turn // Input: fname - the output filename // Output: a file that contains the // Author: Greg Shaw // Created: 8/24/93 int fileutil::cycle_sections(int type, char *fname) { CardRec user; // dummy for files object 'open' FILE *infile; // for reading bbs files master header FILE *outfile; // output text file for some functions time_t now; // current time int x; char ftype; // type of files section char c; // char char *u; // simple char pointer char *bbsdir; // home of BBS char word[25]; // word char datestr[12]; // date string storage char tmpstr[255]; // temp str char name[MAX_FILENAMELENGTH]; // section name char dn_path[255]; // download path char long_desc[255]; // long description struct tm *tmrec; bbsdir = getenv("BBSDIR"); if (bbsdir == NULL) { printf("Unable to get BBSDIR environment variable."); exit(0); } list_obj.clear_list(); // nuke old values sprintf(tmpstr,"%s/filehdr/bbs_files_hdr",bbsdir);// tack on files header if (infile = bopen(tmpstr,"r"), infile == NULL) { sprintf(tmpstr,"fileutil: Unable to open main files section header (bbs_files_hdr)",name); ap_log(tmpstr); return(-1); } // ok. got file. let's loop through list for each section if ((type == 0 || type == 1) && (outfile = bopen(fname,"w"), outfile == NULL)) { sprintf(tmpstr,"fileutil: Unable to open output file %s",fname); ap_log(tmpstr); return(-1); } switch(type) { case 0: // new files time(&now); tmrec = localtime(&now); strftime(datestr,11,"%x",tmrec); fprintf(outfile,"New files in the last %d days. (%s)\n",DAYS,datestr); fprintf(outfile,"Name Section Date by Downloads\n"); break; case 1: // most popular files time(&now); tmrec = localtime(&now); strftime(datestr,11,"%x",tmrec); fprintf(outfile,"Most popular files on BBS by downloads: (%s)\n",datestr); fprintf(outfile,"Name Section Dls Date Uploaded by\n"); break; case 2: // update sections time(&now); tmrec = localtime(&now); strftime(datestr,11,"%x",tmrec); printf("SysOp Report for BBS: (%s)\n",datestr); printf("Section Size Files Missing New Deleted\n"); break; case 3: // delete missing files from bbs and headers time(&now); tmrec = localtime(&now); strftime(datestr,11,"%x",tmrec); printf("Deleted Files Report for BBS: (%s)\n",datestr); printf("Section Deleted\n"); break; } while (!feof(infile)) { // look for left bracket while (c = fgetc(infile), c != '[' && !feof(infile)); // now get the rest of the line if (feof(infile)) continue; if (x = fscanf(infile,"%s %c %*s %*s %*d %s %*s %*d%50s",name,&ftype,dn_path, long_desc), x != 4) { sprintf(tmpstr,"Error in bbs main files header (%s: Expected 4, got %d).",name,x); ap_log(tmpstr); return(-1); } if (ftype == 'C') { // printf("CD-ROM filesection %s skipped.\n",name); } else if (ftype == 'R') { while (fscanf(infile,"%s",word) == 1 && strchr(word,']') == NULL) { strcat(long_desc," "); strcat(long_desc,word); } if (u = strchr(long_desc,']'), u != NULL) u[0] = 0; // turn into null // open section if (open(name,&user) != 0) { sprintf(tmpstr,"fileutil: error opening %s",name); ap_log(tmpstr); bclose(infile); bclose(outfile); return(-1); } // now pass to appropriate function switch(type) { case 0: // generate new files list newfiles(long_desc,outfile); break; case 1: // generate most popular files list most(long_desc); break; case 2: // update files section update(name); break; case 3: // delete missing files delete_missing(long_desc,name); break; default: return(0); } } else // unknown filesection type { sprintf(tmpstr,"fileutil: unknown filesection type %c for %s",ftype,name); ap_log(tmpstr); return(1); } } if (type == 1) // most popular files? { // then generate list from 20 files for (x=0; x