filedat.c 21.5 KB
Newer Older
1
2
3
4
/* filedat.c */

/* Synchronet file database-related exported functions */

5
/* $Id: filedat.c,v 1.40 2019/01/12 08:11:13 rswindell Exp $ */
6
7
8
9
10

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
11
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 *																			*
 * This program 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			*
 * of the License, or (at your option) any later version.					*
 * See the GNU General Public License for more details: gpl.txt or			*
 * http://www.fsf.org/copyleft/gpl.html										*
 *																			*
 * Anonymous FTP access to the most recent released source is available at	*
 * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
 *																			*
 * Anonymous CVS access to the development source and modification history	*
 * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
 *     (just hit return, no password is necessary)							*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * You are encouraged to submit any modifications (preferably in Unix diff	*
 * format) via e-mail to mods@synchro.net									*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

#include "sbbs.h"

/****************************************************************************/
/* Gets filedata from dircode.DAT file										*/
/* Need fields .name ,.dir and .offset to get other info    				*/
/* Does not fill .dateuled or .datedled fields.                             */
/****************************************************************************/
45
BOOL DLLCALL getfiledat(scfg_t* cfg, file_t* f)
46
{
47
	char buf[F_LEN+1],str[MAX_PATH+1];
48
49
50
	int file;
	long length;

51
	SAFEPRINTF2(str,"%s%s.dat",cfg->dir[f->dir]->data_dir,cfg->dir[f->dir]->code);
52
53
54
	if((file=sopen(str,O_RDONLY|O_BINARY,SH_DENYWR))==-1) {
		return(FALSE); 
	}
55
	length=(long)filelength(file);
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
	if(f->datoffset>length) {
		close(file);
		return(FALSE); 
	}
	if(length%F_LEN) {
		close(file);
		return(FALSE); 
	}
	lseek(file,f->datoffset,SEEK_SET);
	if(read(file,buf,F_LEN)!=F_LEN) {
		close(file);
		return(FALSE); 
	}
	close(file);
	getrec(buf,F_ALTPATH,2,str);
	f->altpath=hptoi(str);
	getrec(buf,F_CDT,LEN_FCDT,str);
	f->cdt=atol(str);

rswindell's avatar
rswindell committed
75
76
77
78
79
80
81
82
83
	if(f->size == 0) {					// only read disk if f->size == 0
		struct stat st;
		getfilepath(cfg,f,str);
		if(stat(str, &st) == 0) {
			f->size = st.st_size;
			f->date = (time32_t)st.st_mtime;
		} else
			f->size = -1;	// indicates file does not exist
	}
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#if 0
	if((f->size>0L) && cur_cps)
		f->timetodl=(ushort)(f->size/(ulong)cur_cps);
	else
#endif
		f->timetodl=0;

	getrec(buf,F_DESC,LEN_FDESC,f->desc);
	getrec(buf,F_ULER,LEN_ALIAS,f->uler);
	getrec(buf,F_TIMESDLED,5,str);
	f->timesdled=atoi(str);
	getrec(buf,F_OPENCOUNT,3,str);
	f->opencount=atoi(str);
	if(buf[F_MISC]!=ETX)
98
		f->misc=buf[F_MISC]-' ';
99
100
101
102
103
104
105
106
107
	else
		f->misc=0;
	return(TRUE);
}

/****************************************************************************/
/* Puts filedata into DIR_code.DAT file                                     */
/* Called from removefiles                                                  */
/****************************************************************************/
108
BOOL DLLCALL putfiledat(scfg_t* cfg, file_t* f)
109
{
110
    char buf[F_LEN+1],str[MAX_PATH+1],tmp[128];
111
112
113
114
115
116
117
118
    int file;
    long length;

	putrec(buf,F_CDT,LEN_FCDT,ultoa(f->cdt,tmp,10));
	putrec(buf,F_DESC,LEN_FDESC,f->desc);
	putrec(buf,F_DESC+LEN_FDESC,2,crlf);
	putrec(buf,F_ULER,LEN_ALIAS+5,f->uler);
	putrec(buf,F_ULER+LEN_ALIAS+5,2,crlf);
119
	putrec(buf,F_TIMESDLED,5,ultoa(f->timesdled,tmp,10));
120
	putrec(buf,F_TIMESDLED+5,2,crlf);
121
	putrec(buf,F_OPENCOUNT,3,ultoa(f->opencount,tmp,10));
122
	putrec(buf,F_OPENCOUNT+3,2,crlf);
123
	buf[F_MISC]=(char)f->misc+' ';
124
125
	putrec(buf,F_ALTPATH,2,hexplus(f->altpath,tmp));
	putrec(buf,F_ALTPATH+2,2,crlf);
126
	SAFEPRINTF2(str,"%s%s.dat",cfg->dir[f->dir]->data_dir,cfg->dir[f->dir]->code);
127
128
129
	if((file=sopen(str,O_WRONLY|O_BINARY,SH_DENYRW))==-1) {
		return(FALSE); 
	}
130
	length=(long)filelength(file);
131
132
133
134
135
136
137
138
139
140
141
142
143
	if(length%F_LEN) {
		close(file);
		return(FALSE); 
	}
	if(f->datoffset>length) {
		close(file);
		return(FALSE); 
	}
	lseek(file,f->datoffset,SEEK_SET);
	if(write(file,buf,F_LEN)!=F_LEN) {
		close(file);
		return(FALSE); 
	}
144
	length=(long)filelength(file);
145
146
147
148
149
150
151
152
153
154
155
156
	close(file);
	if(length%F_LEN) {
		return(FALSE);
	}
	return(TRUE);
}

/****************************************************************************/
/* Adds the data for struct filedat to the directory's data base.           */
/* changes the .datoffset field only                                        */
/* returns 1 if added successfully, 0 if not.								*/
/****************************************************************************/
157
BOOL DLLCALL addfiledat(scfg_t* cfg, file_t* f)
158
{
159
	char	str[MAX_PATH+1],fname[13],c,fdat[F_LEN+1];
160
	char	tmp[128];
deuce's avatar
deuce committed
161
	uchar	*ixbbuf,idx[3];
162
163
164
165
166
167
168
    int		i,file;
	long	l,length;
	time_t	uldate;

	/************************/
	/* Add data to DAT File */
	/************************/
169
	SAFEPRINTF2(str,"%s%s.dat",cfg->dir[f->dir]->data_dir,cfg->dir[f->dir]->code);
170
	if((file=sopen(str,O_RDWR|O_BINARY|O_CREAT,SH_DENYRW,DEFFILEMODE))==-1) {
171
172
		return(FALSE); 
	}
173
	length=(long)filelength(file);
174
175
176
177
178
179
180
181
182
183
184
185
	if(length==0L)
		l=0L;
	else {
		if(length%F_LEN) {
			close(file);
			return(FALSE); 
		}
		for(l=0;l<length;l+=F_LEN) {    /* Find empty slot */
			lseek(file,l,SEEK_SET);
			read(file,&c,1);
			if(c==ETX) break; 
		}
186
		if(l/F_LEN>=MAX_FILES) {
187
188
189
190
191
192
193
194
195
196
197
			close(file);
			return(FALSE); 
		} 
	}
	putrec(fdat,F_CDT,LEN_FCDT,ultoa(f->cdt,tmp,10));
	putrec(fdat,F_DESC,LEN_FDESC,f->desc);
	putrec(fdat,F_DESC+LEN_FDESC,2,crlf);
	putrec(fdat,F_ULER,LEN_ALIAS+5,f->uler);
	putrec(fdat,F_ULER+LEN_ALIAS+5,2,crlf);
	putrec(fdat,F_TIMESDLED,5,ultoa(f->timesdled,tmp,10));
	putrec(fdat,F_TIMESDLED+5,2,crlf);
198
	putrec(fdat,F_OPENCOUNT,3,ultoa(f->opencount,tmp,10));
199
	putrec(fdat,F_OPENCOUNT+3,2,crlf);
200
	fdat[F_MISC]=(char)f->misc+' ';
201
202
203
204
205
206
207
208
209
210
211
	putrec(fdat,F_ALTPATH,2,hexplus(f->altpath,tmp));
	putrec(fdat,F_ALTPATH+2,2,crlf);
	f->datoffset=l;
	idx[0]=(uchar)(l&0xff);          /* Get offset within DAT file for IXB file */
	idx[1]=(uchar)((l>>8)&0xff);
	idx[2]=(uchar)((l>>16)&0xff);
	lseek(file,l,SEEK_SET);
	if(write(file,fdat,F_LEN)!=F_LEN) {
		close(file);
		return(FALSE); 
	}
212
	length=(long)filelength(file);
213
214
215
216
217
218
219
220
	close(file);
	if(length%F_LEN) {
		return(FALSE);
	}

	/*******************************************/
	/* Update last upload date/time stamp file */
	/*******************************************/
221
	SAFEPRINTF2(str,"%s%s.dab",cfg->dir[f->dir]->data_dir,cfg->dir[f->dir]->code);
222
	if((file=sopen(str,O_WRONLY|O_CREAT|O_BINARY,SH_DENYRW,DEFFILEMODE))!=-1) {
223
224
225
		time32_t now=time32(NULL);
		/* TODO: LE required */
		write(file,&now,sizeof(time32_t));
226
227
228
229
230
231
		close(file); 
	}

	/************************/
	/* Add data to IXB File */
	/************************/
232
	SAFECOPY(fname,f->name);
233
234
	for(i=8;i<12;i++)   /* Turn FILENAME.EXT into FILENAMEEXT */
		fname[i]=fname[i+1];
235
	SAFEPRINTF2(str,"%s%s.ixb",cfg->dir[f->dir]->data_dir,cfg->dir[f->dir]->code);
236
	if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW,DEFFILEMODE))==-1) {
237
238
		return(FALSE); 
	}
239
	length=(long)filelength(file);
240
241
242
243
244
	if(length) {    /* IXB file isn't empty */
		if(length%F_IXBSIZE) {
			close(file);
			return(FALSE); 
		}
deuce's avatar
deuce committed
245
		if((ixbbuf=(uchar *)malloc(length))==NULL) {
246
247
248
249
250
			close(file);
			return(FALSE); 
		}
		if(lread(file,ixbbuf,length)!=length) {
			close(file);
251
			free(ixbbuf);
252
253
254
255
256
257
258
			return(FALSE); 
		}
	/************************************************/
	/* Sort by Name or Date, Assending or Decending */
	/************************************************/
		if(cfg->dir[f->dir]->sort==SORT_NAME_A || cfg->dir[f->dir]->sort==SORT_NAME_D) {
			for(l=0;l<length;l+=F_IXBSIZE) {
259
				for(i=0;i<12 && toupper(fname[i])==toupper(ixbbuf[l+i]);i++);
260
261
				if(i==12) {     /* file already in directory index */
					close(file);
262
					free(ixbbuf);
263
264
					return(FALSE); 
				}
265
266
				if(cfg->dir[f->dir]->sort==SORT_NAME_A 
					&& toupper(fname[i])<toupper(ixbbuf[l+i]))
267
					break;
268
269
				if(cfg->dir[f->dir]->sort==SORT_NAME_D 
					&& toupper(fname[i])>toupper(ixbbuf[l+i]))
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
					break; 
			} 
		}
		else {  /* sort by date */
			for(l=0;l<length;l+=F_IXBSIZE) {
				uldate=(ixbbuf[l+14]|((long)ixbbuf[l+15]<<8)
					|((long)ixbbuf[l+16]<<16)|((long)ixbbuf[l+17]<<24));
				if(cfg->dir[f->dir]->sort==SORT_DATE_A && f->dateuled<uldate)
					break;
				if(cfg->dir[f->dir]->sort==SORT_DATE_D && f->dateuled>uldate)
					break; 
			} 
		}
		lseek(file,l,SEEK_SET);
		if(write(file,fname,11)!=11) {  /* Write filename to IXB file */
			close(file);
286
			free(ixbbuf);
287
288
289
290
			return(FALSE); 
		}
		if(write(file,idx,3)!=3) {  /* Write DAT offset into IXB file */
			close(file);
291
			free(ixbbuf);
292
293
			return(FALSE); 
		}
deuce's avatar
64-bit    
deuce committed
294
		write(file,&f->dateuled,4);
295
296
297
		write(file,&f->datedled,4);              /* Write 0 for datedled */
		if(lwrite(file,&ixbbuf[l],length-l)!=length-l) { /* Write rest of IXB */
			close(file);
298
			free(ixbbuf);
299
300
			return(FALSE); 
		}
301
		free(ixbbuf); 
302
	}
303
304
305
306
307
308
309
310
311
	else {              /* IXB file is empty... No files */
		if(write(file,fname,11)!=11) {  /* Write filename it IXB file */
			close(file);
			return(FALSE); 
		}
		if(write(file,idx,3)!=3) {  /* Write DAT offset into IXB file */
			close(file);
			return(FALSE); 
		}
deuce's avatar
64-bit    
deuce committed
312
		write(file,&f->dateuled,4);
313
314
		write(file,&f->datedled,4); 
	}
315
	length=(long)filelength(file);
316
317
318
319
320
	close(file);
	return(TRUE);
}

/****************************************************************************/
321
/* Gets file data from dircode.ixb file										*/
322
323
324
/* Need fields .name and .dir filled.                                       */
/* only fills .offset, .dateuled, and .datedled                             */
/****************************************************************************/
325
BOOL DLLCALL getfileixb(scfg_t* cfg, file_t* f)
326
{
327
	char			str[MAX_PATH+1],fname[13];
deuce's avatar
deuce committed
328
	uchar *	ixbbuf;
329
330
331
	int				file;
	long			l,length;

332
	SAFEPRINTF2(str,"%s%s.ixb",cfg->dir[f->dir]->data_dir,cfg->dir[f->dir]->code);
333
334
335
	if((file=sopen(str,O_RDONLY|O_BINARY,SH_DENYWR))==-1) {
		return(FALSE); 
	}
336
	length=(long)filelength(file);
337
338
339
340
	if(length%F_IXBSIZE) {
		close(file);
		return(FALSE); 
	}
deuce's avatar
deuce committed
341
	if((ixbbuf=(uchar *)malloc(length))==NULL) {
342
343
344
345
346
		close(file);
		return(FALSE); 
	}
	if(lread(file,ixbbuf,length)!=length) {
		close(file);
347
		free(ixbbuf);
348
349
350
		return(FALSE); 
	}
	close(file);
351
	SAFECOPY(fname,f->name);
352
353
354
	for(l=8;l<12;l++)	/* Turn FILENAME.EXT into FILENAMEEXT */
		fname[l]=fname[l+1];
	for(l=0;l<length;l+=F_IXBSIZE) {
355
		SAFEPRINTF(str,"%11.11s",ixbbuf+l);
356
		if(!stricmp(str,fname))
357
358
359
			break; 
	}
	if(l>=length) {
360
		free(ixbbuf);
361
362
363
364
365
366
367
368
		return(FALSE); 
	}
	l+=11;
	f->datoffset=ixbbuf[l]|((long)ixbbuf[l+1]<<8)|((long)ixbbuf[l+2]<<16);
	f->dateuled=ixbbuf[l+3]|((long)ixbbuf[l+4]<<8)
		|((long)ixbbuf[l+5]<<16)|((long)ixbbuf[l+6]<<24);
	f->datedled=ixbbuf[l+7]|((long)ixbbuf[l+8]<<8)
		|((long)ixbbuf[l+9]<<16)|((long)ixbbuf[l+10]<<24);
369
	free(ixbbuf);
370
371
372
	return(TRUE);
}

373
374
375
376
377
378
379
380
381
382
383
384
385
386
/****************************************************************************/
/* Updates the datedled and dateuled index record fields for a file			*/
/****************************************************************************/
BOOL DLLCALL putfileixb(scfg_t* cfg, file_t* f)
{
	char	str[MAX_PATH+1],fname[13];
	uchar*	ixbbuf;
	int		file;
	long	l,length;

	SAFEPRINTF2(str,"%s%s.ixb",cfg->dir[f->dir]->data_dir,cfg->dir[f->dir]->code);
	if((file=sopen(str,O_RDWR|O_BINARY,SH_DENYRW))==-1) {
		return(FALSE); 
	}
387
	length=(long)filelength(file);
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
	if(length%F_IXBSIZE) {
		close(file);
		return(FALSE); 
	}
	if((ixbbuf=(uchar *)malloc(length))==NULL) {
		close(file);
		return(FALSE); 
	}
	if(lread(file,ixbbuf,length)!=length) {
		close(file);
		free(ixbbuf);
		return(FALSE); 
	}
	SAFECOPY(fname,f->name);
	for(l=8;l<12;l++)	/* Turn FILENAME.EXT into FILENAMEEXT */
		fname[l]=fname[l+1];
	for(l=0;l<length;l+=F_IXBSIZE) {
		SAFEPRINTF(str,"%11.11s",ixbbuf+l);
		if(!stricmp(str,fname))
			break; 
	}
	free(ixbbuf);

	if(l>=length) {
		close(file);
		return(FALSE); 
	}
	
	lseek(file,l+11+3,SEEK_SET);

deuce's avatar
64-bit    
deuce committed
418
419
	write(file,&f->dateuled,4);
	write(file,&f->datedled,4);
420
421
422
423
424
425
426

	close(file);

	return(TRUE);
}


427
428
429
/****************************************************************************/
/* Removes DAT and IXB entries for the file in the struct 'f'               */
/****************************************************************************/
430
BOOL DLLCALL removefiledat(scfg_t* cfg, file_t* f)
431
{
deuce's avatar
deuce committed
432
	char	c,str[MAX_PATH+1],ixbname[12],*ixbbuf,fname[13];
433
    int		i,file;
434
435
	long	l,length;

436
	SAFECOPY(fname,f->name);
437
438
	for(i=8;i<12;i++)   /* Turn FILENAME.EXT into FILENAMEEXT */
		fname[i]=fname[i+1];
439
	SAFEPRINTF2(str,"%s%s.ixb",cfg->dir[f->dir]->data_dir,cfg->dir[f->dir]->code);
440
441
442
	if((file=sopen(str,O_RDONLY|O_BINARY,SH_DENYWR))==-1) {
		return(FALSE); 
	}
443
	length=(long)filelength(file);
444
445
446
447
	if(!length) {
		close(file);
		return(FALSE); 
	}
deuce's avatar
deuce committed
448
	if((ixbbuf=(char *)malloc(length))==0) {
449
450
451
452
453
		close(file);
		return(FALSE); 
	}
	if(lread(file,ixbbuf,length)!=length) {
		close(file);
454
		free(ixbbuf);
455
456
457
458
		return(FALSE); 
	}
	close(file);
	if((file=sopen(str,O_WRONLY|O_TRUNC|O_BINARY,SH_DENYRW))==-1) {
459
		free(ixbbuf);
460
461
462
		return(FALSE); 
	}
	for(l=0;l<length;l+=F_IXBSIZE) {
463
464
465
		for(i=0;i<11;i++)
			ixbname[i]=ixbbuf[l+i];
		ixbname[i]=0;
466
		if(stricmp(ixbname,fname))
467
468
			if(lwrite(file,&ixbbuf[l],F_IXBSIZE)!=F_IXBSIZE) {
				close(file);
469
				free(ixbbuf);
470
471
472
				return(FALSE); 
		} 
	}
473
	free(ixbbuf);
474
	close(file);
475
	SAFEPRINTF2(str,"%s%s.dat",cfg->dir[f->dir]->data_dir,cfg->dir[f->dir]->code);
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
	if((file=sopen(str,O_WRONLY|O_BINARY,SH_DENYRW))==-1) {
		return(FALSE); 
	}
	lseek(file,f->datoffset,SEEK_SET);
	c=ETX;          /* If first char of record is ETX, record is unused */
	if(write(file,&c,1)!=1) { /* So write a D_T on the first byte of the record */
		close(file);
		return(FALSE); 
	}
	close(file);
	if(f->dir==cfg->user_dir)  /* remove file from index */
		rmuserxfers(cfg,0,0,f->name);
	return(TRUE);
}

/****************************************************************************/
/* Checks  directory data file for 'filename' (must be padded). If found,   */
/* it returns the 1, else returns 0.                                        */
/* Called from upload and bulkupload                                        */
/****************************************************************************/
496
BOOL DLLCALL findfile(scfg_t* cfg, uint dirnum, char *filename)
497
{
deuce's avatar
deuce committed
498
	char str[MAX_PATH+1],fname[13],*ixbbuf;
499
    int i,file;
500
501
    long length,l;

502
	SAFECOPY(fname,filename);
503
	strupr(fname);
504
505
	for(i=8;i<12;i++)   /* Turn FILENAME.EXT into FILENAMEEXT */
		fname[i]=fname[i+1];
506
	SAFEPRINTF2(str,"%s%s.ixb",cfg->dir[dirnum]->data_dir,cfg->dir[dirnum]->code);
507
	if((file=sopen(str,O_RDONLY|O_BINARY,SH_DENYWR))==-1) return(FALSE);
508
	length=(long)filelength(file);
509
510
	if(!length) {
		close(file);
511
512
		return(FALSE); 
	}
deuce's avatar
deuce committed
513
	if((ixbbuf=(char *)malloc(length))==NULL) {
514
		close(file);
515
516
		return(FALSE); 
	}
517
518
	if(lread(file,ixbbuf,length)!=length) {
		close(file);
519
		free(ixbbuf);
520
521
		return(FALSE); 
	}
522
523
	close(file);
	for(l=0;l<length;l+=F_IXBSIZE) {
524
		for(i=0;i<11;i++)
525
			if(toupper(fname[i])!=toupper(ixbbuf[l+i])) break;
526
527
		if(i==11) break; 
	}
528
	free(ixbbuf);
529
530
531
532
533
534
535
536
	if(l!=length)
		return(TRUE);
	return(FALSE);
}

/****************************************************************************/
/* Turns FILE.EXT into FILE    .EXT                                         */
/****************************************************************************/
537
char* DLLCALL padfname(const char *filename, char *str)
538
{
539
    int c,d;
540
541
542
543
544
545
546

	for(c=0;c<8;c++)
		if(filename[c]=='.' || !filename[c]) break;
		else str[c]=filename[c];
	d=c;
	if(filename[c]=='.') c++;
	while(d<8)
547
548
549
550
551
		str[d++]=' ';
	if(filename[c]>' ')	/* Change "FILE" to "FILE        " */
		str[d++]='.';	/* (don't add a dot if there's no extension) */
	else
		str[d++]=' ';
552
553
554
555
	while(d<12)
		if(!filename[c]) break;
		else str[d++]=filename[c++];
	while(d<12)
556
		str[d++]=' ';
557
558
559
560
561
562
563
	str[d]=0;
	return(str);
}

/****************************************************************************/
/* Turns FILE    .EXT into FILE.EXT                                         */
/****************************************************************************/
564
char* DLLCALL unpadfname(const char *filename, char *str)
565
{
566
    int c,d;
567
568

	for(c=0,d=0;filename[c];c++)
569
		if(filename[c]!=' ') str[d++]=filename[c];
570
571
572
573
574
575
576
577
	str[d]=0;
	return(str);
}

/****************************************************************************/
/* Removes any files in the user transfer index (XFER.IXT) that match the   */
/* specifications of dest, or source user, or filename or any combination.  */
/****************************************************************************/
578
BOOL DLLCALL rmuserxfers(scfg_t* cfg, int fromuser, int destuser, char *fname)
579
{
580
    char str[MAX_PATH+1],*ixtbuf;
581
582
583
    int file;
    long l,length;

584
	SAFEPRINTF(str,"%sxfer.ixt", cfg->data_dir);
585
586
587
588
589
590
	if(!fexist(str))
		return(FALSE);
	if(!flength(str)) {
		remove(str);
		return(FALSE); 
	}
591
	if((file=sopen(str,O_RDONLY|O_BINARY,SH_DENYWR))==-1) {
592
593
		return(FALSE); 
	}
594
	length=(long)filelength(file);
deuce's avatar
deuce committed
595
	if((ixtbuf=(char *)malloc(length))==NULL) {
596
597
598
599
600
		close(file);
		return(FALSE); 
	}
	if(read(file,ixtbuf,length)!=length) {
		close(file);
deuce's avatar
deuce committed
601
		free(ixtbuf);
602
603
604
605
		return(FALSE); 
	}
	close(file);
	if((file=sopen(str,O_WRONLY|O_TRUNC|O_BINARY,SH_DENYRW))==-1) {
deuce's avatar
deuce committed
606
		free(ixtbuf);
607
608
609
610
611
612
613
		return(FALSE); 
	}
	for(l=0;l<length;l+=24) {
		if(fname!=NULL && fname[0]) {               /* fname specified */
			if(!strncmp(ixtbuf+l+5,fname,12)) {     /* this is the file */
				if(destuser && fromuser) {          /* both dest and from user */
					if(atoi(ixtbuf+l)==destuser && atoi(ixtbuf+l+18)==fromuser)
614
615
						continue;                   /* both match */
				}
616
617
				else if(fromuser) {                 /* from user */
					if(atoi(ixtbuf+l+18)==fromuser) /* matches */
618
619
						continue; 
				}
620
621
				else if(destuser) {                 /* dest user */
					if(atoi(ixtbuf+l)==destuser)    /* matches */
622
623
624
625
626
						continue; 
				}
				else continue;		                /* no users, so match */
			}
		}
627
628
		else if(destuser && fromuser) {
			if(atoi(ixtbuf+l+18)==fromuser && atoi(ixtbuf+l)==destuser)
629
630
				continue; 
		}
631
632
633
634
		else if(destuser && atoi(ixtbuf+l)==destuser)
			continue;
		else if(fromuser && atoi(ixtbuf+l+18)==fromuser)
			continue;
635
636
		write(file,ixtbuf+l,24); 
	}
637
	close(file);
deuce's avatar
deuce committed
638
	free(ixtbuf);
639
640
641
642

	return(TRUE);
}

643
644
void DLLCALL getextdesc(scfg_t* cfg, uint dirnum, ulong datoffset, char *ext)
{
645
	char str[MAX_PATH+1];
646
647
	int file;

648
	memset(ext,0,F_EXBSIZE+1);
649
	SAFEPRINTF2(str,"%s%s.exb",cfg->dir[dirnum]->data_dir,cfg->dir[dirnum]->code);
650
651
	if((file=nopen(str,O_RDONLY))==-1)
		return;
652
653
	lseek(file,(datoffset/F_LEN)*F_EXBSIZE,SEEK_SET);
	read(file,ext,F_EXBSIZE);
654
655
656
657
658
	close(file);
}

void DLLCALL putextdesc(scfg_t* cfg, uint dirnum, ulong datoffset, char *ext)
{
659
	char str[MAX_PATH+1],nulbuf[F_EXBSIZE];
660
661
	int file;

662
	strip_ansi(ext);
663
	strip_invalid_attr(ext);	/* eliminate bogus ctrl-a codes */
664
	memset(nulbuf,0,sizeof(nulbuf));
665
	SAFEPRINTF2(str,"%s%s.exb",cfg->dir[dirnum]->data_dir,cfg->dir[dirnum]->code);
666
667
668
	if((file=nopen(str,O_WRONLY|O_CREAT))==-1)
		return;
	lseek(file,0L,SEEK_END);
669
670
671
672
	while(filelength(file)<(long)(datoffset/F_LEN)*F_EXBSIZE)
		write(file,nulbuf,sizeof(nulbuf));
	lseek(file,(datoffset/F_LEN)*F_EXBSIZE,SEEK_SET);
	write(file,ext,F_EXBSIZE);
673
674
	close(file);
}
675
676
677
678
679
680

/****************************************************************************/
/* Update the upload date for the file 'f'                                  */
/****************************************************************************/
int DLLCALL update_uldate(scfg_t* cfg, file_t* f)
{
681
	char str[MAX_PATH+1],fname[13];
682
683
684
685
686
687
	int i,file;
	long l,length;

	/*******************/
	/* Update IXB File */
	/*******************/
688
	SAFEPRINTF2(str,"%s%s.ixb",cfg->dir[f->dir]->data_dir,cfg->dir[f->dir]->code);
689
690
	if((file=nopen(str,O_RDWR))==-1)
		return(errno); 
691
	length=(long)filelength(file);
692
693
694
695
	if(length%F_IXBSIZE) {
		close(file);
		return(-1); 
	}
696
	SAFECOPY(fname,f->name);
697
698
699
700
701
	for(i=8;i<12;i++)   /* Turn FILENAME.EXT into FILENAMEEXT */
		fname[i]=fname[i+1];
	for(l=0;l<length;l+=F_IXBSIZE) {
		read(file,str,F_IXBSIZE);      /* Look for the filename in the IXB file */
		str[11]=0;
702
		if(!stricmp(fname,str)) break; 
703
	}
704
705
706
707
708
709
710
711
712
713
714
	if(l>=length) {
		close(file);
		return(-2); 
	}
	lseek(file,l+14,SEEK_SET);
	write(file,&f->dateuled,4);
	close(file);

	/*******************************************/
	/* Update last upload date/time stamp file */
	/*******************************************/
715
	SAFEPRINTF2(str,"%s%s.dab",cfg->dir[f->dir]->data_dir,cfg->dir[f->dir]->code);
716
717
718
719
720
721
722
	if((file=nopen(str,O_WRONLY|O_CREAT))==-1)
		return(errno);

	write(file,&f->dateuled,4);
	close(file); 
	return(0);
}
723
724

/****************************************************************************/
725
/* Returns full (case-corrected) path to specified file						*/
726
727
728
729
730
731
/****************************************************************************/
char* DLLCALL getfilepath(scfg_t* cfg, file_t* f, char* path)
{
	char	fname[MAX_PATH+1];

	unpadfname(f->name,fname);
732
	if(f->dir>=cfg->total_dirs)
733
		safe_snprintf(path,MAX_PATH,"%s%s",cfg->temp_dir,fname);
734
	else
735
		safe_snprintf(path,MAX_PATH,"%s%s",f->altpath>0 && f->altpath<=cfg->altpaths 
736
737
			? cfg->altpath[f->altpath-1] : cfg->dir[f->dir]->path
			,fname);
738
	fexistcase(path);
739
740
	return(path);
}