addfiles.c 24 KB
Newer Older
1
2
3
4
5
6
7
8
/* Program to add files to a Synchronet file database */

/* $Id$ */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
9
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
10
11
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
 *																			*
 * 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"

38
#define ADDFILES_VER "3.03"
39
40
41
42
43
44
45

scfg_t scfg;

int cur_altpath=0;

long files=0,removed=0,mode=0;

46
47
char lib[LEN_GSNAME+1];

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#define DEL_LIST	(1L<<0)
#define NO_EXTEND	(1L<<1)
#define FILE_DATE	(1L<<2)
#define TODAYS_DATE (1L<<3)
#define FILE_ID 	(1L<<4)
#define NO_UPDATE	(1L<<5)
#define NO_NEWDATE	(1L<<6)
#define ASCII_ONLY	(1L<<7)
#define UL_STATS	(1L<<8)
#define ULDATE_ONLY (1L<<9)
#define KEEP_DESC	(1L<<10)
#define AUTO_ADD	(1L<<11)
#define SEARCH_DIR	(1L<<12)
#define SYNC_LIST	(1L<<13)
#define KEEP_SPACE	(1L<<14)
rswindell's avatar
rswindell committed
63
#define CHECK_DATE	(1L<<15)
64
65

/****************************************************************************/
66
/* This is needed by load_cfg.c												*/
67
/****************************************************************************/
68
int lprintf(int level, const char *fmat, ...)
69
70
{
	va_list argptr;
71
	char sbuf[512];
72
73
74
75
76
	int chcount;

	va_start(argptr,fmat);
	chcount=vsprintf(sbuf,fmat,argptr);
	va_end(argptr);
77
78
	truncsp(sbuf);
	printf("%s\n",sbuf);
79
80
81
	return(chcount);
}

82
void prep_desc(char *str)
83
84
85
86
87
{
	char tmp[1024];
	int i,j;

	for(i=j=0;str[i] && j < sizeof(tmp)-1;i++) {
88
		if(j && str[i]==' ' && tmp[j-1]==' ' && (mode&KEEP_SPACE))
89
			tmp[j++]=str[i];
90
		else if(j && str[i]<=' ' && str[i] > 0&& tmp[j-1]==' ')
91
			continue;
92
		else if(i && !isalnum((uchar)str[i]) && str[i]==str[i-1])
93
			continue;
94
		else if(str[i]>=' ' || str[i]<0)
95
96
			tmp[j++]=str[i];
		else if(str[i]==TAB || (str[i]==CR && str[i+1]==LF))
97
			tmp[j++]=' ';
98
99
100
101
102
	}
	tmp[j]=0;
	strcpy(str,tmp);
}

103
104
105
/*****************************************************************************/
/* Returns command line generated from instr with %c replacments             */
/*****************************************************************************/
106
char *mycmdstr(const char *instr, const char *fpath, const char *fspec, char *outstr)
107
108
109
110
{
    static char cmd[MAX_PATH+1];
    char str[MAX_PATH+1];
    int i,j,len;
rswindell's avatar
rswindell committed
111
112
113
#ifdef _WIN32
	char sfpath[MAX_PATH+1];
#endif
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

	len=strlen(instr);
	for(i=j=0;i<len && j<128;i++) {
		if(instr[i]=='%') {
			i++;
			cmd[j]=0;
			switch(toupper(instr[i])) {
				case 'F':   /* File path */
					strcat(cmd,fpath);
					break;
				case '~':	/* DOS-compatible (8.3) filename */
#ifdef _WIN32
					SAFECOPY(sfpath,fpath);
					GetShortPathName(fpath,sfpath,sizeof(sfpath));
					strcat(cmd,sfpath);
#else
                    strcat(cmd,fpath);
131
#endif
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
					break;
				case 'G':   /* Temp directory */
					strcat(cmd,scfg.temp_dir);
					break;
                case 'J':
                    strcat(cmd,scfg.data_dir);
                    break;
                case 'K':
                    strcat(cmd,scfg.ctrl_dir);
                    break;
				case 'N':   /* Node Directory (same as SBBSNODE environment var) */
					strcat(cmd,scfg.node_dir);
					break;
				case 'S':   /* File Spec */
					strcat(cmd,fspec);
					break;
                case 'Z':
                    strcat(cmd,scfg.text_dir);
                    break;
				case '!':   /* EXEC Directory */
					strcat(cmd,scfg.exec_dir);
					break;
154
155
156
157
158
                case '@':   /* EXEC Directory for DOS/OS2/Win32, blank for Unix */
#ifndef __unix__
                    strcat(cmd,scfg.exec_dir);
#endif
                    break;
159
160
161
162
163
164
165
166
				case '#':   /* Node number (same as SBBSNNUM environment var) */
					sprintf(str,"%d",scfg.node_num);
					strcat(cmd,str);
					break;
				case '%':   /* %% for percent sign */
					strcat(cmd,"%");
					break;
				default:    /* unknown specification */
167
					break;
168
			}
169
			j=strlen(cmd);
170
171
		}
		else
172
			cmd[j++]=instr[i];
173
174
175
176
177
178
179
180
181
182
183
184
185
	}
	cmd[j]=0;

	return(cmd);
}

/****************************************************************************/
/* Updates dstst.dab file													*/
/****************************************************************************/
void updatestats(ulong size)
{
    char	str[MAX_PATH+1];
    int		file;
deuce's avatar
64-bit    
deuce committed
186
	uint32_t	l;
187

188
	sprintf(str,"%sdsts.dab",scfg.ctrl_dir);
189
	if((file=nopen(str,O_RDWR|O_BINARY))==-1) {
190
		printf("ERR_OPEN %s\n",str);
191
		return;
192
193
194
195
196
197
198
199
200
201
202
203
204
	}
	lseek(file,20L,SEEK_SET);	/* Skip timestamp, logons and logons today */
	read(file,&l,4);			/* Uploads today		 */
	l++;
	lseek(file,-4L,SEEK_CUR);
	write(file,&l,4);
	read(file,&l,4);			/* Upload bytes today	 */
	l+=size;
	lseek(file,-4L,SEEK_CUR);
	write(file,&l,4);
	close(file);
}

205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
void get_file_diz(file_t* f, const char* filepath)
{
	int i,file;
	char tmp[MAX_PATH+1];
	char ext[1024],tmpext[513];

	for(i=0;i<scfg.total_fextrs;i++)
		if(!stricmp(scfg.fextr[i]->ext,f->name+9) && chk_ar(&scfg,scfg.fextr[i]->ar,/* user: */NULL, /* client: */NULL))
			break;
	if(i<scfg.total_fextrs) {
		sprintf(tmp,"%sFILE_ID.DIZ",scfg.temp_dir);
		removecase(tmp);
		system(mycmdstr(scfg.fextr[i]->cmd,filepath,"FILE_ID.DIZ",NULL));
		if(!fexistcase(tmp)) {
			sprintf(tmp,"%sDESC.SDI",scfg.temp_dir);
			removecase(tmp);
			system(mycmdstr(scfg.fextr[i]->cmd,filepath,"DESC.SDI",NULL));
			fexistcase(tmp);
		}
		if((file=nopen(tmp,O_RDONLY|O_BINARY))!=-1) {
			memset(ext,0,513);
			read(file,ext,512);
			for(i=512;i;i--)
				if(ext[i-1]>' ' || ext[i-1]<0)
					break;
			ext[i]=0;
			if(mode&ASCII_ONLY)
				strip_exascii(ext, ext);
			if(!(mode&KEEP_DESC)) {
				sprintf(tmpext,"%.256s",ext);
				prep_desc(tmpext);
				for(i=0;tmpext[i];i++)
					if(isalpha((uchar)tmpext[i]))
						break;
				sprintf(f->desc,"%.*s",LEN_FDESC,tmpext+i);
				for(i=0;(f->desc[i]>=' ' || f->desc[i]<0) && i<LEN_FDESC;i++)
					;
				f->desc[i]=0; }
			close(file);
			f->misc|=FM_EXTDESC;
		}
	}
}

249
250
void addlist(char *inpath, file_t f, uint dskip, uint sskip)
{
251
252
253
254
255
256
	char str[MAX_PATH+1];
	char tmp[MAX_PATH+1];
	char fname[MAX_PATH+1];
	char listpath[MAX_PATH+1];
	char filepath[MAX_PATH+1];
	char curline[256],nextline[256];
257
	char *p;
258
259
	char ext[1024];
	int i;
260
	long l;
261
	BOOL exist;
262
263
264
265
266
	FILE *stream;
	DIR*	dir;
	DIRENT*	dirent;

	if(mode&SEARCH_DIR) {
267
		SAFECOPY(str,cur_altpath ? scfg.altpath[cur_altpath-1] : scfg.dir[f.dir]->path);
268
269
270
271
		printf("Searching %s\n\n",str);
		dir=opendir(str);

		while(dir!=NULL && (dirent=readdir(dir))!=NULL) {
rswindell's avatar
rswindell committed
272
273
274
			sprintf(tmp,"%s%s"
				,cur_altpath ? scfg.altpath[cur_altpath-1] : scfg.dir[f.dir]->path
				,dirent->d_name);
275
276
277
278
279
			if(isdir(tmp))
				continue;
#ifdef _WIN32
			GetShortPathName(tmp, filepath, sizeof(filepath));
#else
280
			SAFECOPY(filepath,tmp);
281
#endif
282
283
284
			f.misc=0;
			f.desc[0]=0;
			f.cdt=flength(filepath);
rswindell's avatar
rswindell committed
285
			time_t file_timestamp = fdate(filepath);
286
			padfname(getfname(filepath),f.name);
deuce's avatar
deuce committed
287
			printf("%s  %10"PRIu32"  %s\n"
rswindell's avatar
rswindell committed
288
				,f.name,f.cdt,unixtodstr(&scfg,(time32_t)file_timestamp,str));
289
290
291
292
			exist=findfile(&scfg,f.dir,f.name);
			if(exist) {
				if(mode&NO_UPDATE)
					continue;
293
294
295
296
297
298
				if(!getfileixb(&scfg,&f)) {
					fprintf(stderr, "!ERROR reading index of directory %u\n", f.dir);
					continue;
				}
				if((mode&CHECK_DATE) && file_timestamp <= f.dateuled)
					continue;
299
				if(mode&ULDATE_ONLY) {
300
					f.dateuled=time32(NULL);
301
					update_uldate(&scfg, &f);
302
303
					continue;
				}
304
305
306
			}

			if(mode&FILE_DATE) {		/* get the file date and put into desc */
rswindell's avatar
rswindell committed
307
				unixtodstr(&scfg,(time32_t)file_timestamp,f.desc);
308
				strcat(f.desc,"  ");
309
310
311
			}

			if(mode&TODAYS_DATE) {		/* put today's date in desc */
312
				unixtodstr(&scfg,time32(NULL),f.desc);
313
				strcat(f.desc,"  ");
314
315
			}

316
317
			if(mode&FILE_ID)
				get_file_diz(&f, filepath);
318

319
			f.dateuled=time32(NULL);
320
			f.altpath=cur_altpath;
321
			prep_desc(f.desc);
322
			if(mode&ASCII_ONLY)
323
				strip_exascii(f.desc, f.desc);
324
325
326
			if(exist) {
				putfiledat(&scfg,&f);
				if(!(mode&NO_NEWDATE))
327
					update_uldate(&scfg, &f);
328
			}
329
330
331
332
			else
				addfiledat(&scfg,&f);
			if(f.misc&FM_EXTDESC) {
				truncsp(ext);
333
				putextdesc(&scfg,f.dir,f.datoffset,ext);
334
			}
335
336
			if(mode&UL_STATS)
				updatestats(f.cdt);
337
			files++;
338
339
340
		}
		if(dir!=NULL)
			closedir(dir);
341
		return;
342
343
344
	}


345
	SAFECOPY(listpath,inpath);
346
	fexistcase(listpath);
347
	if((stream=fopen(listpath,"r"))==NULL) {
348
349
		fprintf(stderr,"Error %d (%s) opening %s\n"
			,errno,strerror(errno),listpath);
350
351
		sprintf(listpath,"%s%s",cur_altpath ? scfg.altpath[cur_altpath-1]
				: scfg.dir[f.dir]->path,inpath);
352
		fexistcase(listpath);
353
		if((stream=fopen(listpath,"r"))==NULL) {
354
355
			printf("Can't open: %s\n"
				   "        or: %s\n",inpath,listpath);
356
357
			return;
		}
358
	}
359
360
361
362
363

	printf("Adding %s to %s %s\n\n"
		,listpath,scfg.lib[scfg.dir[f.dir]->lib]->sname,scfg.dir[f.dir]->sname);

	fgets(nextline,255,stream);
364
	do {
365
366
		f.misc=0;
		f.desc[0]=0;
367
		SAFECOPY(curline,nextline);
368
369
370
		nextline[0]=0;
		fgets(nextline,255,stream);
		truncsp(curline);
371
		if(curline[0]<=' ' || (mode&ASCII_ONLY && (uchar)curline[0]>=0x7e))
372
373
			continue;
		printf("%s\n",curline);
374
		SAFECOPY(fname,curline);
375

376
#if 0	/* Files without dots are valid on modern systems */
377
378
379
		p=strchr(fname,'.');
		if(!p || p==fname || p>fname+8)    /* no dot or invalid dot location */
			continue;
380
381
#endif
		p=strchr(fname,' ');
382
383
384
		if(p) *p=0;
		else				   /* no space after filename? */
			continue;
385
#if 0
386
		strupr(fname);
387
#endif
388
		SAFECOPY(fname,unpadfname(fname,tmp));
389

390
391
392
393
394
395
396
397
398
399
400
		sprintf(filepath,"%s%s",cur_altpath ? scfg.altpath[cur_altpath-1]
			: scfg.dir[f.dir]->path,fname);

#ifdef _WIN32
		{
			char shortpath[MAX_PATH+1];
			GetShortPathName(filepath, shortpath, sizeof(shortpath));
			SAFECOPY(fname, getfname(shortpath));
		}
#endif

401
402
403
404
405
		padfname(fname,f.name);
		if(strcspn(f.name,"\\/|<>+[]:=\";,")!=strlen(f.name))
			continue;

		for(i=0;i<12;i++)
406
			if(f.name[i]<' ' || (mode&ASCII_ONLY && (uchar)f.name[i]>0x7e))
407
408
409
410
				break;

		if(i<12)					/* Ctrl chars or EX-ASCII in filename? */
			continue;
rswindell's avatar
rswindell committed
411
		time_t file_timestamp = fdate(filepath);
412
413
414
415
		exist=findfile(&scfg,f.dir,f.name);
		if(exist) {
			if(mode&NO_UPDATE)
				continue;
416
417
418
419
420
421
			if(!getfileixb(&scfg,&f)) {
				fprintf(stderr, "!ERROR reading index of directory %u\n", f.dir);
				continue;
			}
			if((mode&CHECK_DATE) && file_timestamp <= f.dateuled)
				continue;
422
			if(mode&ULDATE_ONLY) {
423
				f.dateuled=time32(NULL);
424
				update_uldate(&scfg, &f);
425
426
				continue;
			}
427
		}
428
429

		if(mode&FILE_DATE) {		/* get the file date and put into desc */
rswindell's avatar
rswindell committed
430
			unixtodstr(&scfg,(time32_t)file_timestamp,f.desc);
431
			strcat(f.desc,"  ");
432
		}
433
434

		if(mode&TODAYS_DATE) {		/* put today's date in desc */
435
			l=time32(NULL);
436
			unixtodstr(&scfg,l,f.desc);
437
			strcat(f.desc,"  ");
438
		}
439
440
441

		if(dskip && strlen(curline)>=dskip) p=curline+dskip;
		else {
442
443
			p = curline;
			FIND_WHITESPACE(p);
444
			SKIP_WHITESPACE(p);
445
		}
446
447
448
		SAFECOPY(tmp,p);
		prep_desc(tmp);
		sprintf(f.desc+strlen(f.desc),"%.*s",(int)(LEN_FDESC-strlen(f.desc)),tmp);
449

450
		if(nextline[0]==' ' || strlen(p)>LEN_FDESC) {	/* ext desc */
451
452
453
			if(!(mode&NO_EXTEND)) {
				memset(ext,0,513);
				f.misc|=FM_EXTDESC;
454
				sprintf(ext,"%s\r\n",p);
455
			}
456

457
			if(nextline[0]==' ') {
458
				SAFECOPY(str,nextline);				   /* tack on to end of desc */
459
				p=str+dskip;
460
				while(*p>0 && *p<=' ') p++;
461
462
463
464
465
466
				i=LEN_FDESC-strlen(f.desc);
				if(i>1) {
					p[i-1]=0;
					truncsp(p);
					if(p[0]) {
						strcat(f.desc," ");
467
468
469
						strcat(f.desc,p);
					}
				}
470
			}
471
472

			while(!feof(stream) && !ferror(stream) && strlen(ext)<512) {
473
				if(nextline[0]!=' ')
474
475
476
477
478
479
					break;
				truncsp(nextline);
				printf("%s\n",nextline);
				if(!(mode&NO_EXTEND)) {
					f.misc|=FM_EXTDESC;
					p=nextline+dskip;
480
					while(*p==' ') p++;
481
					strcat(ext,p);
482
					strcat(ext,"\r\n");
483
				}
484
				nextline[0]=0;
485
486
				fgets(nextline,255,stream);
			}
487
		}
488
489
490
491
492


		if(sskip) l=atol(fname+sskip);
		else {
			l=flength(filepath);
493
			if(l<0L) {
494
				printf("%s not found.\n",filepath);
495
496
				continue;
			}
497
498
			if(l == 0L) {
				printf("%s is a zero-0length file.\n",filepath);
499
500
				continue;
			}
501
		}
502

503
504
		if(mode&FILE_ID)
			get_file_diz(&f, filepath);
505
506

		f.cdt=l;
507
		f.dateuled=time32(NULL);
508
		f.altpath=cur_altpath;
509
		prep_desc(f.desc);
510
		if(mode&ASCII_ONLY)
511
			strip_exascii(f.desc, f.desc);
512
513
514
		if(exist) {
			putfiledat(&scfg,&f);
			if(!(mode&NO_NEWDATE))
515
				update_uldate(&scfg, &f);
516
		}
517
518
519
520
		else
			addfiledat(&scfg,&f);
		if(f.misc&FM_EXTDESC) {
			truncsp(ext);
521
			putextdesc(&scfg,f.dir,f.datoffset,ext);
522
		}
523
524
525

		if(mode&UL_STATS)
			updatestats(l);
526
		files++;
527
	} while(!feof(stream) && !ferror(stream));
528
529
530
	fclose(stream);
	if(mode&DEL_LIST && !(mode&SYNC_LIST)) {
		printf("\nDeleting %s\n",listpath);
531
		remove(listpath);
532
	}
533
534
535
536
537

}

void synclist(char *inpath, int dirnum)
{
538
	char	str[1024];
539
540
541
	char	fname[MAX_PATH+1];
	char	listpath[MAX_PATH+1];
	uchar*	ixbbuf;
542
	char*	p;
543
544
545
546
	int		i,file,found;
	long	l,m,length;
	FILE*	stream;
	file_t	f;
547

548
	sprintf(str,"%s%s.ixb",scfg.dir[dirnum]->data_dir,scfg.dir[dirnum]->code);
549
	if((file=nopen(str,O_RDONLY|O_BINARY))==-1) {
550
		printf("ERR_OPEN %s\n",str);
551
		return;
552
	}
553
554
555
	length=filelength(file);
	if(length%F_IXBSIZE) {
		close(file);
rswindell's avatar
rswindell committed
556
		printf("ERR_LEN (%ld) of %s\n",length,str);
557
		return;
558
	}
deuce's avatar
deuce committed
559
	if((ixbbuf=(uchar *)malloc(length))==NULL) {
560
561
		close(file);
		printf("ERR_ALLOC %s\n",str);
562
		return;
563
	}
564
565
	if(lread(file,ixbbuf,length)!=length) {
		close(file);
deuce's avatar
deuce committed
566
		free((char *)ixbbuf);
567
		printf("ERR_READ %s\n",str);
568
		return;
569
	}
570
571
	close(file);

572
	SAFECOPY(listpath,inpath);
573
	if((stream=fopen(listpath,"r"))==NULL) {
574
575
		sprintf(listpath,"%s%s",cur_altpath ? scfg.altpath[cur_altpath-1]
				: scfg.dir[dirnum]->path,inpath);
576
		if((stream=fopen(listpath,"r"))==NULL) {
577
578
			printf("Can't open: %s\n"
				   "        or: %s\n",inpath,listpath);
579
580
			return;
		}
581
	}
582
583
584
585
586
587
588
589

	printf("\nSynchronizing %s with %s %s\n\n"
		,listpath,scfg.lib[scfg.dir[dirnum]->lib]->sname,scfg.dir[dirnum]->sname);

	for(l=0;l<length;l+=F_IXBSIZE) {
		m=l;
		for(i=0;i<12 && l<length;i++)
			if(i==8)
590
				str[i]=ixbbuf[m]>' ' ? '.' : ' ';
591
592
593
594
595
596
597
598
599
600
			else
				str[i]=ixbbuf[m++]; 	/* Turns FILENAMEEXT into FILENAME.EXT */
		str[i]=0;
		unpadfname(str,fname);
		rewind(stream);
		found=0;
		while(!found) {
			if(!fgets(str,1000,stream))
				break;
			truncsp(str);
601
			p=strchr(str,' ');
602
603
			if(p) *p=0;
			if(!stricmp(str,fname))
604
				found=1;
605
		}
606
607
608
609
610
611
		if(found)
			continue;
		padfname(fname,f.name);
		printf("%s not found in list - ",f.name);
		f.dir=dirnum;
		f.datoffset=ixbbuf[m]|((long)ixbbuf[m+1]<<8)|((long)ixbbuf[m+2]<<16);
612
613
614
615
		if(!getfiledat(&scfg,&f)) {
			fprintf(stderr, "!ERROR reading index of directory %u\n", f.dir);
			continue;
		}
616
617
		if(f.opencount) {
			printf("currently OPEN by %u users\n",f.opencount);
618
			continue;
619
		}
620
		removefiledat(&scfg,&f);
621
		if(remove(getfilepath(&scfg,&f,str)))
622
623
			printf("Error removing %s\n",str);
		removed++;
624
		printf("Removed from database\n");
625
	}
626
627
628

	if(mode&DEL_LIST) {
		printf("\nDeleting %s\n",listpath);
629
		remove(listpath);
630
	}
631
632
}

633
char *usage="\nusage: addfiles code [.alt_path] [-opts] +list "
634
			 "[desc_off] [size_off]"
635
	"\n   or: addfiles code [.alt_path] [-opts] file "
636
637
		"\"description\"\n"
	"\navailable opts:"
638
639
640
641
642
643
644
645
646
647
	"\n      -a         import ASCII only (no extended ASCII)"
	"\n      -b         synchronize database with file list (use with caution)"
	"\n      -c         do not remove extra spaces from file description"
	"\n      -d         delete list after import"
	"\n      -e         do not import extended descriptions"
	"\n      -f         include file date in descriptions"
	"\n      -t         include today's date in descriptions"
	"\n      -i         include added files in upload statistics"
	"\n      -n         do not update information for existing files"
	"\n      -o         update upload date only for existing files"
rswindell's avatar
rswindell committed
648
	"\n      -p         compare file date with upload date for existing files"
649
650
651
652
653
654
	"\n      -u         do not update upload date for existing files"
	"\n      -z         check for and import FILE_ID.DIZ and DESC.SDI"
	"\n      -k         keep original short description (not DIZ)"
	"\n      -s         search directory for files (no file list)"
	"\n      -l <lib>   specify library (short name) to Auto-ADD"
	"\n      -x <name>  specify uploader's user name (may require quotes)"
655
	"\n"
656
657
	"\nAuto-ADD:   use - in place of code for Auto-ADD of FILES.BBS"
	"\n            use -filename to Auto-ADD a different filename"
658
	"\n            use -l \"libname\" to only Auto-ADD files to a specific library"
659
660
661
662
663
664
665
666
	;

/*********************/
/* Entry point (duh) */
/*********************/
int main(int argc, char **argv)
{
	char error[512];
667
	char revision[16];
668
669
	char str[MAX_PATH+1];
	char tmp[MAX_PATH+1];
670
671
	char *p;
	char exist,listgiven=0,namegiven=0,ext[513]
672
		,auto_name[MAX_PATH+1]="FILES.BBS";
673
	int i,j;
674
	uint desc_offset=0, size_offset=0;
675
676
677
	long l;
	file_t	f;

678
	sscanf("$Revision$", "%*s %s", revision);
679

680
	fprintf(stderr,"\nADDFILES v%s-%s (rev %s) - Adds Files to Synchronet "
681
682
683
		"Filebase\n"
		,ADDFILES_VER
		,PLATFORM_DESC
684
		,revision
685
686
687
		);

	if(argc<2) {
688
		puts(usage);
689
		return(1);
690
	}
691
692
693
694
695

	p=getenv("SBBSCTRL");
	if(p==NULL) {
		printf("\nSBBSCTRL environment variable not set.\n");
		printf("\nExample: SET SBBSCTRL=/sbbs/ctrl\n");
696
		exit(1);
697
698
	}

699
700
	memset(&scfg,0,sizeof(scfg));
	scfg.size=sizeof(scfg);
701
	SAFECOPY(scfg.ctrl_dir,p);
702
703
704
705
706

	if(chdir(scfg.ctrl_dir)!=0)
		fprintf(stderr,"!ERROR changing directory to: %s", scfg.ctrl_dir);

	printf("\nLoading configuration files from %s\n",scfg.ctrl_dir);
707
708
709
710
	if(!load_cfg(&scfg,NULL,TRUE,error)) {
		fprintf(stderr,"!ERROR loading configuration files: %s\n",error);
		exit(1);
	}
rswindell's avatar
rswindell committed
711
712
	SAFECOPY(scfg.temp_dir,"../temp");
	prep_dir(scfg.ctrl_dir, scfg.temp_dir, sizeof(scfg.temp_dir));
713

714
715
	if(argv[1][0]=='*' || argv[1][0]=='-') {
		if(argv[1][1]=='?') {
716
			puts(usage);
717
718
			exit(0);
		}
719
		if(argv[1][1])
720
			SAFECOPY(auto_name,argv[1]+1);
721
		mode|=AUTO_ADD;
722
		i=0;
723
	} else {
724
		if(!isalnum((uchar)argv[1][0]) && argc==2) {
725
			puts(usage);
726
			return(1);
727
728
		}

729
		for(i=0;i<scfg.total_dirs;i++)
730
			if(!stricmp(scfg.dir[i]->code,argv[1])) /* use matchmatchi() instead? */
731
732
733
734
				break;

		if(i>=scfg.total_dirs) {
			printf("Directory code '%s' not found.\n",argv[1]);
735
736
			exit(1);
		}
737
	}
738
739
740

	memset(&f,0,sizeof(file_t));
	f.dir=i;
741
	SAFECOPY(f.uler,"-> ADDFILES <-");
742
743

	for(j=2;j<argc;j++) {
744
745
		if(argv[j][0]=='*')     /* set the uploader name (legacy) */
			SAFECOPY(f.uler,argv[j]+1);
746
		else
747
748
749
			if(argv[j][0]=='-'
			|| argv[j][0]=='/'
			) {      /* options */
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
			for(i=1;argv[j][i];i++)
				switch(toupper(argv[j][i])) {
					case 'A':
						mode|=ASCII_ONLY;
						break;
					case 'B':
						mode|=(SYNC_LIST|NO_UPDATE);
						break;
					case 'C':
						mode|=KEEP_SPACE;
						break;
					case 'D':
						mode|=DEL_LIST;
						break;
					case 'E':
						mode|=NO_EXTEND;
						break;
					case 'I':
						mode|=UL_STATS;
						break;
770
771
772
					case 'L':
						j++;
						if(argv[j]==NULL) {
773
							puts(usage);
774
775
776
777
778
							return(-1);
						}
						SAFECOPY(lib,argv[j]);
						i=strlen(argv[j])-1;
						break;
779
780
781
					case 'X':
						j++;
						if(argv[j]==NULL) {
782
							puts(usage);
783
784
785
786
787
							return(-1);
						}
						SAFECOPY(f.uler,argv[j]);
						i=strlen(argv[j])-1;
						break;
788
789
790
791
792
793
794
795
796
797
798
799
					case 'Z':
						mode|=FILE_ID;
						break;
					case 'K':
						mode|=KEEP_DESC;	 /* Don't use DIZ for short desc */
						break;
					case 'N':
						mode|=NO_UPDATE;
						break;
					case 'O':
						mode|=ULDATE_ONLY;
						break;
rswindell's avatar
rswindell committed
800
801
802
					case 'P':
						mode|=CHECK_DATE;
						break;
803
804
805
806
807
808
809
810
811
812
813
814
815
					case 'U':
						mode|=NO_NEWDATE;
						break;
					case 'F':
						mode|=FILE_DATE;
						break;
					case 'T':
						mode|=TODAYS_DATE;
						break;
					case 'S':
						mode|=SEARCH_DIR;
						break;
					default:
816
						puts(usage);
817
818
						return(1);
			}
819
		}
820
		else if(isdigit((uchar)argv[j][0])) {
821
822
823
824
825
826
			if(desc_offset==0)
				desc_offset=atoi(argv[j]);
			else
				size_offset=atoi(argv[j]);
			continue;
		}
827
828
		else if(argv[j][0]=='+') {      /* filelist - FILES.BBS */
			listgiven=1;
rswindell's avatar
rswindell committed
829
			if(argc > j+1
830
				&& isdigit((uchar)argv[j+1][0])) { /* skip x characters before description */
rswindell's avatar
rswindell committed
831
				if(argc > j+2
832
					&& isdigit((uchar)argv[j+2][0])) { /* skip x characters before size */
833
					addlist(argv[j]+1,f,atoi(argv[j+1]),atoi(argv[j+2]));
834
					j+=2;
835
				}
836
837
				else {
					addlist(argv[j]+1,f,atoi(argv[j+1]),0);
838
839
					j++;
				}
840
			}
841
842
843
			else
				addlist(argv[j]+1,f,0,0);
			if(mode&SYNC_LIST)
844
				synclist(argv[j]+1,f.dir);
845
		}
846
847
848
849
		else if(argv[j][0]=='.') {      /* alternate file path */
			cur_altpath=atoi(argv[j]+1);
			if(cur_altpath>scfg.altpaths) {
				printf("Invalid alternate path.\n");
850
851
				exit(1);
			}
852
		}
853
854
855
856
		else {
			namegiven=1;
			padfname(argv[j],f.name);
			f.desc[0]=0;
857
#if 0
858
			strupr(f.name);
859
#endif
860
861
			if(j+1==argc) {
				printf("%s no description given.\n",f.name);
862
				continue;
863
			}
864
865
866
			sprintf(str,"%s%s",cur_altpath ? scfg.altpath[cur_altpath-1]
				: scfg.dir[f.dir]->path,argv[j]);
			if(mode&FILE_DATE)
867
				sprintf(f.desc,"%s  ",unixtodstr(&scfg,(time32_t)fdate(str),tmp));
868
			if(mode&TODAYS_DATE)
869
				sprintf(f.desc,"%s  ",unixtodstr(&scfg,time32(NULL),tmp));
rswindell's avatar
rswindell committed
870
			sprintf(tmp,"%.*s",(int)(LEN_FDESC-strlen(f.desc)),argv[++j]);
871
			SAFECOPY(f.desc,tmp);
872
873
874
			l=flength(str);
			if(l==-1) {
				printf("%s not found.\n",str);
875
				continue;
876
			}
877
878
879
880
			exist=findfile(&scfg,f.dir,f.name);
			if(exist) {
				if(mode&NO_UPDATE)
					continue;
881
882
883
884
885
886
				if(!getfileixb(&scfg,&f)) {
					fprintf(stderr, "!ERROR reading index of directory %u\n", f.dir);
					continue;
				}
				if((mode&CHECK_DATE) && fdate(str) <= f.dateuled)
					continue;
887
				if(mode&ULDATE_ONLY) {
888
					f.dateuled=time32(NULL);
889
					update_uldate(&scfg, &f);
890
891
					continue;
				}
892
			}
893
			f.cdt=l;
894
			f.dateuled=time32(NULL);
895
			f.altpath=cur_altpath;
896
			prep_desc(f.desc);
897
			if(mode&ASCII_ONLY)
898
				strip_exascii(f.desc, f.desc);
deuce's avatar
deuce committed
899
			printf("%s %7"PRIu32" %s\n",f.name,f.cdt,f.desc);
900
901
902
			if(mode&FILE_ID)
				get_file_diz(&f, str);

903
904
905
			if(exist) {
				putfiledat(&scfg,&f);
				if(!(mode&NO_NEWDATE))
906
					update_uldate(&scfg, &f);
907
			}
908
909
910
911
912
913
914
915
			else
				addfiledat(&scfg,&f);

			if(f.misc&FM_EXTDESC)
				putextdesc(&scfg,f.dir,f.datoffset,ext);

			if(mode&UL_STATS)
				updatestats(l);
916
917
			files++;
		}
918
	}
919
920
921

	if(mode&AUTO_ADD) {
		for(i=0;i<scfg.total_dirs;i++) {
922
923
			if(lib[0] && stricmp(scfg.lib[scfg.dir[i]->lib]->sname,lib))
				continue;
924
925
926
927
			if(scfg.dir[i]->misc&DIR_NOAUTO)
				continue;
			f.dir=i;
			if(mode&SEARCH_DIR) {
928
				addlist("",f,desc_offset,size_offset);
929
				continue;
930
			}
931
			sprintf(str,"%s%s.lst",scfg.dir[f.dir]->path,scfg.dir[f.dir]->code);
932
			if(fexistcase(str) && flength(str)>0L) {
933
				printf("Auto-adding %s\n",str);
934
				addlist(str,f,desc_offset,size_offset);
935
936
				if(mode&SYNC_LIST)
					synclist(str,i);
937
				continue;
938
			}
939
			sprintf(str,"%s%s",scfg.dir[f.dir]->path,auto_name);
940
			if(fexistcase(str) && flength(str)>0L) {
941
				printf("Auto-adding %s\n",str);
942
				addlist(str,f,desc_offset,size_offset);
943
944
				if(mode&SYNC_LIST)
					synclist(str,i);
945
946
947
				continue;
			}
		}
948
	}
949
950
951

	else {
		if(!listgiven && !namegiven) {
952
			sprintf(str,"%s%s.lst",scfg.dir[f.dir]->path, scfg.dir[f.dir]->code);
953
			if(!fexistcase(str) || flength(str)<=0L)
954
				sprintf(str,"%s%s",scfg.dir[f.dir]->path, auto_name);
955
			addlist(str,f,desc_offset,size_offset);
956
			if(mode&SYNC_LIST)
957
958
				synclist(str,f.dir);
		}
959
	}
960
961
962
963
964
965
966
967

	printf("\n%lu file(s) added.",files);
	if(removed)
		printf("\n%lu files(s) removed.",removed);
	printf("\n");
	return(0);
}