|
|
1.1 root 1: /* delfiles.c */
2:
3: /* Program to delete expired files from a Synchronet file database */
4:
5: /* $Id: delfiles.c,v 1.4 2006/04/26 19:23:18 rswindell Exp $ */
6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html *
12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: #include "sbbs.h"
39:
40: #define DELFILES_VER "1.01"
41:
42: char tmp[256];
43: char *crlf="\r\n";
44:
45: #define MAX_NOTS 25
46:
47: #define ALL (1L<<0)
48: #define OFFLINE (1L<<1)
49: #define NO_LINK (1L<<2)
50: #define REPORT (1L<<3)
51:
52: void bail(int code)
53: {
54: exit(code);
55: }
56:
57: long lputs(char *str)
58: {
59: char tmp[256];
60: int i,j,k;
61:
62: j=strlen(str);
63: for(i=k=0;i<j;i++) /* remove CRs */
64: if(str[i]==CR && str[i+1]==LF)
65: continue;
66: else
67: tmp[k++]=str[i];
68: tmp[k]=0;
69: return(fputs(tmp,stdout));
70: }
71:
72: /****************************************************************************/
73: /* Performs printf() through local assembly routines */
74: /* Called from everywhere */
75: /****************************************************************************/
76: int lprintf(char *fmat, ...)
77: {
78: va_list argptr;
79: char sbuf[256];
80: int chcount;
81:
82: va_start(argptr,fmat);
83: chcount=vsprintf(sbuf,fmat,argptr);
84: va_end(argptr);
85: lputs(sbuf);
86: return(chcount);
87: }
88:
89: int main(int argc, char **argv)
90: {
91: char str[256],fname[MAX_PATH+1],not[MAX_NOTS][9],nots=0,*p;
92: int i,j,dirnum,libnum,file;
93: ulong l,m;
94: long misc=0;
95: time_t now;
96: file_t workfile;
97: scfg_t cfg;
98: glob_t gl;
99: uchar *ixbbuf;
100:
101: setvbuf(stdout,NULL,_IONBF,0);
102:
103: fprintf(stderr,"\nDELFILES Version %s (%s) - Removes files from Synchronet "
104: "Filebase\n" ,DELFILES_VER, PLATFORM_DESC );
105:
106: if(argc<2) {
107: printf("\n usage: DELFILES <dir_code or * for ALL> [switches]\n");
108: printf("\nswitches: -LIB name All directories of specified library\n");
109: printf(" -NOT code Exclude specific directory\n");
110: printf(" -OFF Remove files that are offline "
111: "(don't exist on disk)\n");
112: printf(" -NOL Remove files with no link "
113: "(don't exist in database)\n");
114: printf(" -RPT Report findings only "
115: "(don't delete any files)\n");
116: return(0); }
117:
118: p=getenv("SBBSCTRL");
119: if(p==NULL) {
120: printf("\nSBBSCTRL environment variable not set.\n");
121: #ifdef __unix__
122: printf("\nExample: export SBBSCTRL=/sbbs/ctrl\n");
123: #else
124: printf("\nExample: SET SBBSCTRL=C:\\SBBS\\CTRL\n");
125: #endif
126: return(1); }
127:
128: memset(&cfg, 0, sizeof(cfg));
129: cfg.size=sizeof(cfg);
130: SAFECOPY(cfg.ctrl_dir, p);
131: backslash(cfg.ctrl_dir);
132:
133: load_cfg(&cfg, NULL, TRUE, str);
134: chdir(cfg.ctrl_dir);
135:
136: if(!(cfg.sys_misc&SM_LOCAL_TZ))
137: putenv("TZ=UTC0");
138:
139: dirnum=libnum=-1;
140: if(argv[1][0]=='*')
141: misc|=ALL;
142: else if(argv[1][0]!='/' && argv[1][0]!='-') {
143: strupr(argv[1]);
144: for(i=0;i<cfg.total_dirs;i++)
145: if(!stricmp(argv[1],cfg.dir[i]->code))
146: break;
147: if(i>=cfg.total_dirs) {
148: printf("\nDirectory code '%s' not found.\n",argv[1]);
149: return(1); }
150: dirnum=i; }
151: for(i=1;i<argc;i++) {
152: if(!stricmp(argv[i]+1,"LIB")) {
153: if(dirnum!=-1) {
154: printf("\nBoth directory code and /LIB parameters were used.\n");
155: return(1); }
156: i++;
157: if(i>=argc) {
158: printf("\nLibrary short name must follow /LIB parameter.\n");
159: return(1); }
160: strupr(argv[i]);
161: for(j=0;j<cfg.total_libs;j++)
162: if(!stricmp(cfg.lib[j]->sname,argv[i]))
163: break;
164: if(j>=cfg.total_libs) {
165: printf("\nLibrary short name '%s' not found.\n",argv[i]);
166: return(1); }
167: libnum=j; }
168: else if(!stricmp(argv[i]+1,"NOT")) {
169: if(nots>=MAX_NOTS) {
170: printf("\nMaximum number of /NOT options (%u) exceeded.\n"
171: ,MAX_NOTS);
172: return(1); }
173: i++;
174: if(i>=argc) {
175: printf("\nDirectory internal code must follow /NOT parameter.\n");
176: return(1); }
177: sprintf(not[nots++],"%.8s",argv[i]); }
178: else if(!stricmp(argv[i]+1,"OFF"))
179: misc|=OFFLINE;
180: else if(!stricmp(argv[i]+1,"NOL"))
181: misc|=NO_LINK;
182: else if(!stricmp(argv[i]+1,"RPT"))
183: misc|=REPORT;
184: else if(!stricmp(argv[i]+1,"ALL")) {
185: if(dirnum!=-1) {
186: printf("\nBoth directory code and /ALL parameters were used.\n");
187: return(1); }
188: if(libnum!=-1) {
189: printf("\nBoth library name and /ALL parameters were used.\n");
190: return(1); }
191: misc|=ALL; } }
192:
193: for(i=0;i<cfg.total_dirs;i++) {
194: if(!(misc&ALL) && i!=dirnum && cfg.dir[i]->lib!=libnum)
195: continue;
196: for(j=0;j<nots;j++)
197: if(!stricmp(not[j],cfg.dir[i]->code))
198: break;
199: if(j<nots)
200: continue;
201:
202: if(misc&NO_LINK && cfg.dir[i]->misc&DIR_FCHK) {
203: strcpy(tmp,cfg.dir[i]->path);
204: sprintf(str,"%s*.*",tmp);
205: printf("\nSearching %s for unlinked files\n",str);
206: if(!glob(str, GLOB_MARK, NULL, &gl)) {
207: for(j=0; j<(int)gl.gl_pathc; j++) {
208: /* emulate _A_NORMAL */
209: if(isdir(gl.gl_pathv[j]))
210: continue;
211: if(access(gl.gl_pathv[j], R_OK|W_OK))
212: continue;
213: padfname(gl.gl_pathv[j],str);
214: /* strupr(str); */
215: if(!findfile(&cfg, i,str)) {
216: sprintf(str,"%s%s",tmp,gl.gl_pathv[j]);
217: printf("Removing %s (not in database)\n",gl.gl_pathv);
218: if(!(misc&REPORT) && remove(str))
219: printf("Error removing %s\n",str); } } }
220: globfree(&gl);
221: }
222:
223: if(!cfg.dir[i]->maxage && !(misc&OFFLINE))
224: continue;
225:
226: printf("\nScanning %s %s\n",cfg.lib[cfg.dir[i]->lib]->sname,cfg.dir[i]->lname);
227:
228: sprintf(str,"%s%s.ixb",cfg.dir[i]->data_dir,cfg.dir[i]->code);
229: if((file=nopen(str,O_RDONLY|O_BINARY))==-1)
230: continue;
231: l=filelength(file);
232: if(!l) {
233: close(file);
234: continue; }
235: if((ixbbuf=(char *)malloc(l))==NULL) {
236: close(file);
237: printf("\7ERR_ALLOC %s %lu\n",str,l);
238: continue; }
239: if(read(file,ixbbuf,l)!=(int)l) {
240: close(file);
241: printf("\7ERR_READ %s %lu\n",str,l);
242: free((char *)ixbbuf);
243: continue; }
244: close(file);
245:
246: m=0L;
247: now=time(NULL);
248: while(m<l) {
249: memset(&workfile,0,sizeof(file_t));
250: for(j=0;j<12 && m<l;j++)
251: if(j==8)
252: fname[j]='.';
253: else
254: fname[j]=ixbbuf[m++];
255: fname[j]=0;
256: strcpy(workfile.name,fname);
257: unpadfname(workfile.name,fname);
258: workfile.dir=i;
259: sprintf(str,"%s%s"
260: ,workfile.altpath>0 && workfile.altpath<=cfg.altpaths
261: ? cfg.altpath[workfile.altpath-1]
262: : cfg.dir[workfile.dir]->path,fname);
263: workfile.datoffset=ixbbuf[m]|((long)ixbbuf[m+1]<<8)
264: |((long)ixbbuf[m+2]<<16);
265: workfile.dateuled=(ixbbuf[m+3]|((long)ixbbuf[m+4]<<8)
266: |((long)ixbbuf[m+5]<<16)|((long)ixbbuf[m+6]<<24));
267: workfile.datedled=(ixbbuf[m+7]|((long)ixbbuf[m+8]<<8)
268: |((long)ixbbuf[m+9]<<16)|((long)ixbbuf[m+10]<<24));
269: m+=11;
270: if(cfg.dir[i]->maxage && cfg.dir[i]->misc&DIR_SINCEDL && workfile.datedled
271: && (now-workfile.datedled)/86400L>cfg.dir[i]->maxage) {
272: printf("Deleting %s (%ld days since last download)\n",fname
273: ,(now-workfile.datedled)/86400L);
274: getfiledat(&cfg, &workfile);
275: if(!(misc&REPORT)) {
276: removefiledat(&cfg, &workfile);
277: if(remove(str))
278: printf("Error removing %s\n",str); } }
279: else if(cfg.dir[i]->maxage
280: && !(workfile.datedled && cfg.dir[i]->misc&DIR_SINCEDL)
281: && (now-workfile.dateuled)/86400L>cfg.dir[i]->maxage) {
282: printf("Deleting %s (uploaded %ld days ago)\n",fname
283: ,(now-workfile.dateuled)/86400L);
284: getfiledat(&cfg, &workfile);
285: if(!(misc&REPORT)) {
286: removefiledat(&cfg, &workfile);
287: if(remove(str))
288: printf("Error removing %s\n",str); } }
289: else if(misc&OFFLINE && cfg.dir[i]->misc&DIR_FCHK && !fexist(str)) {
290: printf("Removing %s (doesn't exist)\n",fname);
291: getfiledat(&cfg, &workfile);
292: if(!(misc&REPORT))
293: removefiledat(&cfg, &workfile); } }
294:
295: free((char *)ixbbuf); }
296:
297: return(0);
298: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.