filedat.c 21.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
/* filedat.c */

/* Synchronet file database-related exported functions */

/* $Id$ */

/****************************************************************************
 * @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 75
	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);

	if(!f->size) {					/* only read disk if this is null */
76
			getfilepath(cfg,f,str);
77
			if((f->size=(long)flength(str))>=0)
78
				f->date=(time32_t)fdate(str);
79 80 81 82
	/*
			}
		else {
			f->size=f->cdt;
83 84
			f->date=0; 
			}
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
	*/
			}
#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)
101
		f->misc=buf[F_MISC]-' ';
102 103 104 105 106 107 108 109 110
	else
		f->misc=0;
	return(TRUE);
}

/****************************************************************************/
/* Puts filedata into DIR_code.DAT file                                     */
/* Called from removefiles                                                  */
/****************************************************************************/
111
BOOL DLLCALL putfiledat(scfg_t* cfg, file_t* f)
112
{
113
    char buf[F_LEN+1],str[MAX_PATH+1],tmp[128];
114 115 116 117 118 119 120 121
    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);
122
	putrec(buf,F_TIMESDLED,5,ultoa(f->timesdled,tmp,10));
123
	putrec(buf,F_TIMESDLED+5,2,crlf);
124
	putrec(buf,F_OPENCOUNT,3,ultoa(f->opencount,tmp,10));
125
	putrec(buf,F_OPENCOUNT+3,2,crlf);
126
	buf[F_MISC]=(char)f->misc+' ';
127 128
	putrec(buf,F_ALTPATH,2,hexplus(f->altpath,tmp));
	putrec(buf,F_ALTPATH+2,2,crlf);
129
	SAFEPRINTF2(str,"%s%s.dat",cfg->dir[f->dir]->data_dir,cfg->dir[f->dir]->code);
130 131 132
	if((file=sopen(str,O_WRONLY|O_BINARY,SH_DENYRW))==-1) {
		return(FALSE); 
	}
133
	length=(long)filelength(file);
134 135 136 137 138 139 140 141 142 143 144 145 146
	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); 
	}
147
	length=(long)filelength(file);
148 149 150 151 152 153 154 155 156 157 158 159
	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.								*/
/****************************************************************************/
160
BOOL DLLCALL addfiledat(scfg_t* cfg, file_t* f)
161
{
162
	char	str[MAX_PATH+1],fname[13],c,fdat[F_LEN+1];
163
	char	tmp[128];
deuce's avatar
deuce committed
164
	uchar	*ixbbuf,idx[3];
165 166 167 168 169 170 171
    int		i,file;
	long	l,length;
	time_t	uldate;

	/************************/
	/* Add data to DAT File */
	/************************/
172
	SAFEPRINTF2(str,"%s%s.dat",cfg->dir[f->dir]->data_dir,cfg->dir[f->dir]->code);
173
	if((file=sopen(str,O_RDWR|O_BINARY|O_CREAT,SH_DENYRW,DEFFILEMODE))==-1) {
174 175
		return(FALSE); 
	}
176
	length=(long)filelength(file);
177 178 179 180 181 182 183 184 185 186 187 188
	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; 
		}
189
		if(l/F_LEN>=MAX_FILES) {
190 191 192 193 194 195 196 197 198 199 200
			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);
201
	putrec(fdat,F_OPENCOUNT,3,ultoa(f->opencount,tmp,10));
202
	putrec(fdat,F_OPENCOUNT+3,2,crlf);
203
	fdat[F_MISC]=(char)f->misc+' ';
204 205 206 207 208 209 210 211 212 213 214
	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); 
	}
215
	length=(long)filelength(file);
216 217 218 219 220 221 222 223
	close(file);
	if(length%F_LEN) {
		return(FALSE);
	}

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

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

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

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

376 377 378 379 380 381 382 383 384 385 386 387 388 389
/****************************************************************************/
/* 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); 
	}
390
	length=(long)filelength(file);
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 418 419 420
	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
421 422
	write(file,&f->dateuled,4);
	write(file,&f->datedled,4);
423 424 425 426 427 428 429

	close(file);

	return(TRUE);
}


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

439
	SAFECOPY(fname,f->name);
440 441
	for(i=8;i<12;i++)   /* Turn FILENAME.EXT into FILENAMEEXT */
		fname[i]=fname[i+1];
442
	SAFEPRINTF2(str,"%s%s.ixb",cfg->dir[f->dir]->data_dir,cfg->dir[f->dir]->code);
443 444 445
	if((file=sopen(str,O_RDONLY|O_BINARY,SH_DENYWR))==-1) {
		return(FALSE); 
	}
446
	length=(long)filelength(file);
447 448 449 450
	if(!length) {
		close(file);
		return(FALSE); 
	}
deuce's avatar
deuce committed
451
	if((ixbbuf=(char *)malloc(length))==0) {
452 453 454 455 456
		close(file);
		return(FALSE); 
	}
	if(lread(file,ixbbuf,length)!=length) {
		close(file);
457
		free(ixbbuf);
458 459 460 461
		return(FALSE); 
	}
	close(file);
	if((file=sopen(str,O_WRONLY|O_TRUNC|O_BINARY,SH_DENYRW))==-1) {
462
		free(ixbbuf);
463 464 465
		return(FALSE); 
	}
	for(l=0;l<length;l+=F_IXBSIZE) {
466 467 468
		for(i=0;i<11;i++)
			ixbname[i]=ixbbuf[l+i];
		ixbname[i]=0;
469
		if(stricmp(ixbname,fname))
470 471
			if(lwrite(file,&ixbbuf[l],F_IXBSIZE)!=F_IXBSIZE) {
				close(file);
472
				free(ixbbuf);
473 474 475
				return(FALSE); 
		} 
	}
476
	free(ixbbuf);
477
	close(file);
478
	SAFEPRINTF2(str,"%s%s.dat",cfg->dir[f->dir]->data_dir,cfg->dir[f->dir]->code);
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498
	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                                        */
/****************************************************************************/
499
BOOL DLLCALL findfile(scfg_t* cfg, uint dirnum, char *filename)
500
{
deuce's avatar
deuce committed
501
	char str[MAX_PATH+1],fname[13],*ixbbuf;
502
    int i,file;
503 504
    long length,l;

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

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

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

/****************************************************************************/
/* Turns FILE    .EXT into FILE.EXT                                         */
/****************************************************************************/
567
char* DLLCALL unpadfname(const char *filename, char *str)
568
{
569
    int c,d;
570 571

	for(c=0,d=0;filename[c];c++)
572
		if(filename[c]!=' ') str[d++]=filename[c];
573 574 575 576 577 578 579 580
	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.  */
/****************************************************************************/
581
BOOL DLLCALL rmuserxfers(scfg_t* cfg, int fromuser, int destuser, char *fname)
582
{
583
    char str[MAX_PATH+1],*ixtbuf;
584 585 586
    int file;
    long l,length;

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

	return(TRUE);
}

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

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

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

665
	strip_invalid_attr(ext);	/* eliminate bogus ctrl-a codes */
666
	memset(nulbuf,0,sizeof(nulbuf));
667
	SAFEPRINTF2(str,"%s%s.exb",cfg->dir[dirnum]->data_dir,cfg->dir[dirnum]->code);
668 669 670
	if((file=nopen(str,O_WRONLY|O_CREAT))==-1)
		return;
	lseek(file,0L,SEEK_END);
671 672 673 674
	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);
675 676
	close(file);
}
677 678 679 680 681 682

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

	/*******************/
	/* Update IXB File */
	/*******************/
690
	SAFEPRINTF2(str,"%s%s.ixb",cfg->dir[f->dir]->data_dir,cfg->dir[f->dir]->code);
691 692
	if((file=nopen(str,O_RDWR))==-1)
		return(errno); 
693
	length=(long)filelength(file);
694 695 696 697
	if(length%F_IXBSIZE) {
		close(file);
		return(-1); 
	}
698
	SAFECOPY(fname,f->name);
699 700 701 702 703
	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;
704
		if(!stricmp(fname,str)) break; 
705
	}
706 707 708 709 710 711 712 713 714 715 716
	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 */
	/*******************************************/
717
	SAFEPRINTF2(str,"%s%s.dab",cfg->dir[f->dir]->data_dir,cfg->dir[f->dir]->code);
718 719 720 721 722 723 724
	if((file=nopen(str,O_WRONLY|O_CREAT))==-1)
		return(errno);

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

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

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