|
|
1.1 root 1: /* file.cpp */
2:
3: /* Synchronet file transfer-related functions */
4:
5: /* $Id: file.cpp,v 1.5 2000/12/11 23:21:11 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 2000 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: void sbbs_t::getextdesc(uint dirnum, ulong datoffset, char *ext)
41: {
42: char str[256];
43: int file;
44:
45: memset(ext,0,513);
46: sprintf(str,"%s%s.exb",cfg.dir[dirnum]->data_dir,cfg.dir[dirnum]->code);
47: if((file=nopen(str,O_RDONLY))==-1)
48: return;
49: lseek(file,(datoffset/F_LEN)*512L,SEEK_SET);
50: read(file,ext,512);
51: close(file);
52: }
53:
54: void sbbs_t::putextdesc(uint dirnum, ulong datoffset, char *ext)
55: {
56: char str[256],nulbuf[512];
57: int file;
58:
59: memset(nulbuf,0,512);
60: sprintf(str,"%s%s.exb",cfg.dir[dirnum]->data_dir,cfg.dir[dirnum]->code);
61: if((file=nopen(str,O_WRONLY|O_CREAT))==-1)
62: return;
63: lseek(file,0L,SEEK_END);
64: while(filelength(file)<(long)(datoffset/F_LEN)*512L)
65: write(file,nulbuf,512);
66: lseek(file,(datoffset/F_LEN)*512L,SEEK_SET);
67: write(file,ext,512);
68: close(file);
69: }
70:
71: /****************************************************************************/
72: /* Prints all information of file in file_t structure 'f' */
73: /****************************************************************************/
74: void sbbs_t::fileinfo(file_t* f)
75: {
76: char fname[13],ext[513];
77: char tmp[512];
78: uint i,j;
79:
80: for(i=0;i<usrlibs;i++)
81: if(usrlib[i]==cfg.dir[f->dir]->lib)
82: break;
83: for(j=0;j<usrdirs[i];j++)
84: if(usrdir[i][j]==f->dir)
85: break;
86: unpadfname(f->name,fname);
87: bprintf(text[FiLib],i+1,cfg.lib[cfg.dir[f->dir]->lib]->lname);
88: bprintf(text[FiDir],j+1,cfg.dir[f->dir]->lname);
89: bprintf(text[FiFilename],fname);
90: if(f->size!=-1L)
91: bprintf(text[FiFileSize],ultoac(f->size,tmp));
92: bprintf(text[FiCredits]
93: ,(cfg.dir[f->dir]->misc&DIR_FREE || !f->cdt) ? "FREE" : ultoac(f->cdt,tmp));
94: bprintf(text[FiDescription],f->desc);
95: bprintf(text[FiUploadedBy],f->misc&FM_ANON ? text[UNKNOWN_USER] : f->uler);
96: if(f->date)
97: bprintf(text[FiFileDate],timestr(&f->date));
98: bprintf(text[FiDateUled],timestr(&f->dateuled));
99: bprintf(text[FiDateDled],f->datedled ? timestr(&f->datedled) : "Never");
100: bprintf(text[FiTimesDled],f->timesdled);
101: if(f->size!=-1L)
102: bprintf(text[FiTransferTime],sectostr(f->timetodl,tmp));
103: if(f->altpath) {
104: if(f->altpath<=cfg.altpaths) {
105: if(SYSOP)
106: bprintf(text[FiAlternatePath],cfg.altpath[f->altpath-1]); }
107: else
108: bprintf(text[InvalidAlternatePathN],f->altpath); }
109: CRLF;
110: if(f->misc&FM_EXTDESC) {
111: getextdesc(f->dir,f->datoffset,ext);
112: CRLF;
113: putmsg(ext,P_NOATCODES);
114: CRLF; }
115: if(f->size==-1L)
116: bprintf(text[FileIsNotOnline],f->name);
117: if(f->opencount)
118: bprintf(text[FileIsOpen],f->opencount,f->opencount>1 ? "s" : nulstr);
119:
120: }
121:
122:
123: /****************************************************************************/
124: /* Increments the opencount on the file data 'f' and adds the transaction */
125: /* to the backout.dab */
126: /****************************************************************************/
127: void sbbs_t::openfile(file_t* f)
128: {
129: char str1[256],str2[4],str3[4],ch;
130: int file;
131:
132: /************************************/
133: /* Increment open count in dat file */
134: /************************************/
135: sprintf(str1,"%s%s.dat",cfg.dir[f->dir]->data_dir,cfg.dir[f->dir]->code);
136: if((file=nopen(str1,O_RDWR))==-1) {
137: errormsg(WHERE,ERR_OPEN,str1,O_RDWR);
138: return; }
139: lseek(file,f->datoffset+F_OPENCOUNT,SEEK_SET);
140: if(read(file,str2,3)!=3) {
141: close(file);
142: errormsg(WHERE,ERR_READ,str1,3);
143: return; }
144: str2[3]=0;
145: ultoa(atoi(str2)+1,str3,10);
146: putrec(str2,0,3,str3);
147: lseek(file,f->datoffset+F_OPENCOUNT,SEEK_SET);
148: if(write(file,str2,3)!=3) {
149: close(file);
150: errormsg(WHERE,ERR_WRITE,str1,3);
151: return; }
152: close(file);
153: /**********************************/
154: /* Add transaction to BACKOUT.DAB */
155: /**********************************/
156: sprintf(str1,"%sbackout.dab",cfg.node_dir);
157: if((file=nopen(str1,O_WRONLY|O_APPEND|O_CREAT))==-1) {
158: errormsg(WHERE,ERR_OPEN,str1,O_WRONLY|O_APPEND|O_CREAT);
159: return; }
160: ch=BO_OPENFILE;
161: write(file,&ch,1); /* backout type */
162: write(file,cfg.dir[f->dir]->code,8); /* directory code */
163: write(file,&f->datoffset,4); /* offset into .dat file */
164: write(file,&ch,BO_LEN-(1+8+4)); /* pad it */
165: close(file);
166: }
167:
168: /****************************************************************************/
169: /* Decrements the opencount on the file data 'f' and removes the backout */
170: /* from the backout.dab */
171: /****************************************************************************/
172: void sbbs_t::closefile(file_t* f)
173: {
174: char str1[256],str2[4],str3[4],ch,*buf;
175: int file;
176: long length,l,offset;
177:
178: /************************************/
179: /* Decrement open count in dat file */
180: /************************************/
181: sprintf(str1,"%s%s.dat",cfg.dir[f->dir]->data_dir,cfg.dir[f->dir]->code);
182: if((file=nopen(str1,O_RDWR))==-1) {
183: errormsg(WHERE,ERR_OPEN,str1,O_RDWR);
184: return; }
185: lseek(file,f->datoffset+F_OPENCOUNT,SEEK_SET);
186: if(read(file,str2,3)!=3) {
187: close(file);
188: errormsg(WHERE,ERR_READ,str1,3);
189: return; }
190: str2[3]=0;
191: ch=atoi(str2);
192: if(ch) ch--;
193: ultoa(ch,str3,10);
194: putrec(str2,0,3,str3);
195: lseek(file,f->datoffset+F_OPENCOUNT,SEEK_SET);
196: if(write(file,str2,3)!=3) {
197: close(file);
198: errormsg(WHERE,ERR_WRITE,str1,3);
199: return; }
200: close(file);
201: /*****************************************/
202: /* Removing transaction from BACKOUT.DAB */
203: /*****************************************/
204: sprintf(str1,"%sbackout.dab",cfg.node_dir);
205: if(flength(str1)<1L) /* file is not there or empty */
206: return;
207: if((file=nopen(str1,O_RDONLY))==-1) {
208: errormsg(WHERE,ERR_OPEN,str1,O_RDONLY);
209: return; }
210: length=filelength(file);
211: if((buf=(char *)MALLOC(length))==NULL) {
212: close(file);
213: errormsg(WHERE,ERR_ALLOC,str1,length);
214: return; }
215: if(read(file,buf,length)!=length) {
216: close(file);
217: FREE(buf);
218: errormsg(WHERE,ERR_READ,str1,length);
219: return; }
220: close(file);
221: if((file=nopen(str1,O_WRONLY|O_TRUNC))==-1) {
222: errormsg(WHERE,ERR_OPEN,str1,O_WRONLY|O_TRUNC);
223: return; }
224: ch=0; /* 'ch' is a 'file already removed' flag */
225: for(l=0;l<length;l+=BO_LEN) { /* in case file is in backout.dab > 1 */
226: if(!ch && buf[l]==BO_OPENFILE) {
227: memcpy(str1,buf+l+1,8);
228: str1[8]=0;
229: memcpy(&offset,buf+l+9,4);
230: if(!stricmp(str1,cfg.dir[f->dir]->code) && offset==f->datoffset) {
231: ch=1;
232: continue; } }
233: write(file,buf+l,BO_LEN); }
234: FREE(buf);
235: close(file);
236: }
237:
238: /****************************************************************************/
239: /* Prompts user for file specification. <CR> is *.* and .* is assumed. */
240: /* Returns padded file specification. */
241: /* Returns NULL if input was aborted. */
242: /****************************************************************************/
243: char * sbbs_t::getfilespec(char *str)
244: {
245: bputs(text[FileSpecStarDotStar]);
246: if(!getstr(str,12,K_UPPER))
247: strcpy(str,"*.*");
248: else if(!strchr(str,'.') && strlen(str)<=8)
249: strcat(str,".*");
250: if(sys_status&SS_ABORT)
251: return(0);
252: return(str);
253: }
254:
255: /****************************************************************************/
256: /* Checks to see if filename matches filespec. Returns 1 if yes, 0 if no */
257: /****************************************************************************/
258: BOOL filematch(char *filename, char *filespec)
259: {
260: char c;
261:
262: for(c=0;c<8;c++) /* Handle Name */
263: if(filespec[c]=='*') break;
264: else if(filespec[c]=='?') continue;
265: else if(toupper(filename[c])!=toupper(filespec[c])) return(FALSE);
266: for(c=9;c<12;c++)
267: if(filespec[c]=='*') break;
268: else if(filespec[c]=='?') continue;
269: else if(toupper(filename[c])!=toupper(filespec[c])) return(FALSE);
270: return(TRUE);
271: }
272:
273: /****************************************************************************/
274: /* Deletes all files in dir 'path' that match file spec 'spec' */
275: /****************************************************************************/
276: uint sbbs_t::delfiles(char *inpath, char *spec)
277: {
278: char path[MAX_PATH];
279: uint i,files=0;
280: glob_t g;
281:
282: strcpy(path,inpath);
283: backslash(path);
284: strcat(path,spec);
285: glob(path,0,NULL,&g);
286: for(i=0;i<g.gl_pathc;i++) {
287: if(isdir(g.gl_pathv[i]))
288: continue;
289: CHMOD(g.gl_pathv[i],S_IWRITE); // Incase it's been marked RDONLY
290: if(remove(g.gl_pathv[i]))
291: errormsg(WHERE,ERR_REMOVE,g.gl_pathv[i],0);
292: else
293: files++;
294: }
295: globfree(&g);
296: return(files);
297: }
298:
299: /*****************************************************************************/
300: /* Checks the filename 'fname' for invalid symbol or character sequences */
301: /*****************************************************************************/
302: bool sbbs_t::checkfname(char *fname)
303: {
304: char str[256];
305: int c=0,d;
306:
307: if(strcspn(fname,"\\/|<>+[]:=\";,%")!=strlen(fname)) {
308: sprintf(str,"Suspicious filename attempt: '%s'",fname);
309: errorlog(str);
310: return(false); }
311: if(strstr(fname,".."))
312: return(false);
313: if(strcspn(fname,".")>8)
314: return(false);
315: d=strlen(fname);
316: while(c<d) {
317: if(fname[c]<=SP || fname[c]&0x80)
318: return(false);
319: c++; }
320: return(true);
321: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.