addfiles.c 21.9 KB
Newer Older
1
/* Add files to a Synchronet file database(s) */
2
3
4
5
6

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
7
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 *																			*
 * 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										*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

22
23
24
25
26
27
28
#include "nopen.h"
#include "str_util.h"
#include "datewrap.h"
#include "date_str.h"
#include "userdat.h"
#include "filedat.h"
#include "load_cfg.h"
29
30
31
32
#include "smblib.h"
#include "git_branch.h"
#include "git_hash.h"

33
#include <stdbool.h>
34
#include <stdarg.h>
35

36
#define ADDFILES_VER "3.19"
37
38
39
40
41
42
43

scfg_t scfg;

int cur_altpath=0;

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

44
char lib[LEN_GSNAME+1];
45
const char* datefmt = NULL;
46

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#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
62
#define CHECK_DATE	(1L<<15)
63
64

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

	va_start(argptr,fmat);
	chcount=vsprintf(sbuf,fmat,argptr);
	va_end(argptr);
76
77
	truncsp(sbuf);
	printf("%s\n",sbuf);
78
79
80
81
82
83
84
85
86
87
	return(chcount);
}

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

90
	sprintf(str,"%sdsts.dab",scfg.ctrl_dir);
91
	if((file=nopen(str,O_RDWR|O_BINARY))==-1) {
92
		printf("ERR_OPEN %s\n",str);
93
		return;
94
95
96
97
98
99
100
101
102
103
104
105
106
	}
	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);
}

107
bool reupload(smb_t* smb, file_t* f)
108
{
109
	char path[MAX_PATH + 1];
110
	if(smb_renewfile(smb, f, SMB_SELFPACK, getfilepath(&scfg, f, path)) != SMB_SUCCESS) {
111
		fprintf(stderr, "!Error renewing: %s\n", f->name);
112
		return false;
113
	}
114
115
116
	return true;
}

117

118
119
120
121
122
123
124
bool get_file_diz(file_t* f, char* ext, size_t maxlen)
{
	char path[MAX_PATH + 1];
	printf("Extracting DIZ from: %s\n", getfilepath(&scfg, f, path));
	char diz_fpath[MAX_PATH + 1];
	if(!extract_diz(&scfg, f, /* diz_fnames */NULL, diz_fpath, sizeof(diz_fpath))) {
		printf("DIZ does not exist in: %s\n", getfilepath(&scfg, f, path));
125
		return false;
126
127
	}
	printf("Parsing DIZ: %s\n", diz_fpath);
128
	str_list_t lines = read_diz(diz_fpath);
129
130
131
	format_diz(lines, ext, maxlen, /* allow_ansi: */false);
	strListFree(&lines);
	remove(diz_fpath);
132
133
134

	if(mode&ASCII_ONLY)
		strip_exascii(ext, ext);
135

136
	if(!(mode&KEEP_DESC)) {
137
138
139
140
		char* fdesc = strdup(ext);
		smb_new_hfield_str(f, SMB_FILEDESC, prep_file_desc(fdesc, fdesc));
		free(fdesc);
	}
141
	return true;
142
143
}

144
void addlist(char *inpath, uint dirnum, const char* uploader, uint dskip, uint sskip)
145
{
146
147
148
149
150
151
	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];
152
	char *p;
153
154
	char ext[1024];
	int i;
155
	off_t l;
156
	BOOL exist;
157
158
159
	FILE *stream;
	DIR*	dir;
	DIRENT*	dirent;
160
161
	smb_t smb;
	file_t f;
162

163
164
165
166
167
168
	int result = smb_open_dir(&scfg, &smb, dirnum);
	if(result != SMB_SUCCESS) {
		fprintf(stderr, "!Error %d (%s) opening %s\n", result, smb.last_error, smb.file);
		return;
	}
	str_list_t fname_list = loadfilenames(&smb, ALLFILES, /* time: */0, FILE_SORT_NATURAL, /* count: */NULL);
169
	if(mode&SEARCH_DIR) {
170
		SAFECOPY(str,cur_altpath ? scfg.altpath[cur_altpath-1] : scfg.dir[dirnum]->path);
171
172
173
174
		printf("Searching %s\n\n",str);
		dir=opendir(str);

		while(dir!=NULL && (dirent=readdir(dir))!=NULL) {
175
176
			sprintf(filepath, "%s%s"
				,cur_altpath ? scfg.altpath[cur_altpath-1] : scfg.dir[dirnum]->path
rswindell's avatar
rswindell committed
177
				,dirent->d_name);
178
			if(isdir(filepath))
179
				continue;
180
181
182
183
184
185
			const char* fname = getfname(filepath);
			printf("%s  ", fname);
			if(strListFind(fname_list, fname, /* case-sensitive: */FALSE) && (mode&NO_UPDATE)) {
				printf("already added.\n");
				continue;
			}
186
			memset(ext, 0, sizeof(ext));
187
188
189
			memset(&f, 0, sizeof(f));
			char fdesc[LEN_FDESC + 1] = {0};
			uint32_t cdt = (uint32_t)flength(filepath);
rswindell's avatar
rswindell committed
190
			time_t file_timestamp = fdate(filepath);
191
192
193
			printf("%10"PRIu32"  %s\n"
				,cdt, unixtodstr(&scfg,(time32_t)file_timestamp,str));
			exist = smb_findfile(&smb, fname, &f) == SMB_SUCCESS;
194
195
196
			if(exist) {
				if(mode&NO_UPDATE)
					continue;
197
				if((mode&CHECK_DATE) && file_timestamp <= f.idx.time)
198
					continue;
199
				if(mode&ULDATE_ONLY) {
200
201
202
					reupload(&smb, &f);
					continue; 
				} 
203
204
205
			}

			if(mode&TODAYS_DATE) {		/* put today's date in desc */
206
207
208
209
				time_t now = time(NULL);
				if(datefmt) {
					struct tm tm = {0};
					localtime_r(&now, &tm);
210
					strftime(fdesc, sizeof(fdesc), datefmt, &tm);
211
				} else
212
					unixtodstr(&scfg, (time32_t)now, fdesc);
213
				SAFECAT(fdesc,"  ");
214
215
216
217
218
			}
			else if(mode&FILE_DATE) {		/* get the file date and put into desc */
				if(datefmt) {
					struct tm tm = {0};
					localtime_r(&file_timestamp, &tm);
219
					strftime(fdesc, sizeof(fdesc), datefmt, &tm);
220
				} else
221
					unixtodstr(&scfg,(time32_t)file_timestamp,fdesc);
222
				SAFECAT(fdesc,"  ");
223
224
			}

225
226
227
228
229
230
			char* ext_desc = NULL;
			if(mode&FILE_ID) {
				if(get_file_diz(&f, ext, sizeof(ext))) {
					ext_desc = ext;
				}
			}
231

232
			prep_file_desc(fdesc, fdesc);
233
			if(mode&ASCII_ONLY)
234
235
236
237
238
239
240
241
				strip_exascii(fdesc, fdesc);

			smb_hfield_str(&f, SMB_FILENAME, fname);
			smb_hfield_str(&f, SMB_FILEDESC, fdesc);
			smb_hfield_str(&f, SENDER, uploader);
			smb_hfield_bin(&f, SMB_COST, cdt);

			truncsp(ext_desc);
242
			if(exist) {
243
				result = smb_updatemsg(&smb, &f);
244
				if(!(mode&NO_NEWDATE))
245
					reupload(&smb, &f);
246
			}
247
			else
248
249
250
251
				result = smb_addfile(&smb, &f, SMB_SELFPACK, ext_desc, filepath);
			smb_freefilemem(&f);
			if(result != SMB_SUCCESS)
				fprintf(stderr, "!Error %d (%s) adding file to %s", result, smb.last_error, smb.file);
252
			if(mode&UL_STATS)
253
254
				updatestats(cdt);
			files++; 
255
256
257
		}
		if(dir!=NULL)
			closedir(dir);
258
259
260
		smb_close(&smb);
		strListFree(&fname_list);
		return; 
261
262
263
	}


264
	SAFECOPY(listpath,inpath);
265
	fexistcase(listpath);
266
	if((stream=fopen(listpath,"r"))==NULL) {
267
268
		fprintf(stderr,"Error %d (%s) opening %s\n"
			,errno,strerror(errno),listpath);
269
		sprintf(listpath,"%s%s",cur_altpath ? scfg.altpath[cur_altpath-1]
270
				: scfg.dir[dirnum]->path,inpath);
271
		fexistcase(listpath);
272
		if((stream=fopen(listpath,"r"))==NULL) {
273
274
			printf("Can't open: %s\n"
				   "        or: %s\n",inpath,listpath);
275
276
277
278
			smb_close(&smb);
			strListFree(&fname_list);
			return; 
		} 
279
	}
280
281

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

	fgets(nextline,255,stream);
285
	do {
286
		char fdesc[LEN_FDESC + 1] = {0};
287
		memset(ext, 0, sizeof(ext));
288
		SAFECOPY(curline,nextline);
289
290
291
		nextline[0]=0;
		fgets(nextline,255,stream);
		truncsp(curline);
292
		if(curline[0]<=' ' || (mode&ASCII_ONLY && (uchar)curline[0]>=0x7e))
293
294
			continue;
		printf("%s\n",curline);
295
		SAFECOPY(fname,curline);
296

297
		p=strchr(fname,' ');
298
		if(p) *p=0;
rswindell's avatar
rswindell committed
299
#if 0 // allow import of bare filename list
300
301
		else				   /* no space after filename? */
			continue;
rswindell's avatar
rswindell committed
302
#endif
303
		if(!IS_ALPHANUMERIC(*fname)) {	// filename doesn't begin with an alpha-numeric char?
304
305
			continue;
		}
306

307
308
		sprintf(filepath, "%s%s", cur_altpath ? scfg.altpath[cur_altpath-1]
			: scfg.dir[dirnum]->path,fname);
309

310
311
		if(strcspn(fname,"\\/|<>+[]:=\";,")!=strlen(fname)) {
			fprintf(stderr, "!Illegal filename: %s\n", fname);
312
			continue;
313
314
		}

rswindell's avatar
rswindell committed
315
		time_t file_timestamp = fdate(filepath);
316
		memset(&f, 0, sizeof(f));
317
		exist = smb_findfile(&smb, fname, &f) == SMB_SUCCESS;
318
319
320
		if(exist) {
			if(mode&NO_UPDATE)
				continue;
321
			if((mode&CHECK_DATE) && file_timestamp <= f.idx.time)
322
				continue;
323
			if(mode&ULDATE_ONLY) {
324
325
326
				reupload(&smb, &f);
				continue; 
			} 
327
		}
328

329
330
331
		if(mode&FILE_DATE) {		/* get the file date and put into desc */
			unixtodstr(&scfg,(time32_t)file_timestamp, fdesc);
			strcat(fdesc, "  "); 
332
		}
333
334
335
336
337

		if(mode&TODAYS_DATE) {		/* put today's date in desc */
			l=time32(NULL);
			unixtodstr(&scfg,(time32_t)l,fdesc);
			strcat(fdesc, "  "); 
338
		}
339
340
341

		if(dskip && strlen(curline)>=dskip) p=curline+dskip;
		else {
342
343
			p = curline;
			FIND_WHITESPACE(p);
344
			SKIP_WHITESPACE(p);
345
		}
346
		SAFECOPY(tmp,p);
347
348
		prep_file_desc(tmp, tmp);
		sprintf(fdesc + strlen(fdesc), "%.*s", (int)(LEN_FDESC-strlen(fdesc)), tmp);
349

350
		char* ext_desc = NULL;
351
		if(nextline[0]==' ' || strlen(p)>LEN_FDESC) {	/* ext desc */
352
			if(!(mode&NO_EXTEND)) {
353
				memset(ext, 0, sizeof(ext));
354
355
				sprintf(ext,"%s\r\n",p); 
				ext_desc = ext;
356
			}
357

358
			if(nextline[0]==' ') {
359
				SAFECOPY(str,nextline);				   /* tack on to end of desc */
360
				p=str+dskip;
361
				while(*p>0 && *p<=' ') p++;
362
				i=LEN_FDESC-strlen(fdesc);
363
364
365
366
				if(i>1) {
					p[i-1]=0;
					truncsp(p);
					if(p[0]) {
367
368
						SAFECAT(fdesc," ");
						SAFECAT(fdesc,p);
369
370
					}
				}
371
			}
372
373

			while(!feof(stream) && !ferror(stream) && strlen(ext)<512) {
374
				if(nextline[0]!=' ')
375
376
377
378
379
					break;
				truncsp(nextline);
				printf("%s\n",nextline);
				if(!(mode&NO_EXTEND)) {
					p=nextline+dskip;
380
					ext_desc = ext;
381
					while(*p==' ') p++;
382
383
					SAFECAT(ext,p);
					SAFECAT(ext,"\r\n");
384
				}
385
				nextline[0]=0;
386
387
				fgets(nextline,255,stream);
			}
388
		}
389

390
391
392
393
		l=flength(filepath);
		if(l<0L) {
			printf("%s not found.\n",filepath);
			continue;
394
		}
395
396
397
398
399
		if(l == 0L) {
			printf("%s is a zero length file.\n",filepath);
			continue;
		}
		if(sskip) l=atol(fname+sskip);
400

401
		if(mode&FILE_ID)
402
			get_file_diz(&f, ext, sizeof(ext));
403

404
		prep_file_desc(fdesc, fdesc);
405
		if(mode&ASCII_ONLY)
406
407
408
409
410
411
			strip_exascii(fdesc, fdesc);
		uint32_t cdt = (uint32_t)l;
		smb_hfield_bin(&f, SMB_COST, cdt);
		smb_hfield_str(&f, SMB_FILENAME, fname);
		smb_hfield_str(&f, SMB_FILEDESC, fdesc);
		smb_hfield_str(&f, SENDER, uploader);
412
		if(exist) {
413
			result = smb_updatemsg(&smb, &f);
414
			if(!(mode&NO_NEWDATE))
415
				reupload(&smb, &f);
416
		}
417
		else
418
419
420
421
422
			result = smb_addfile(&smb, &f, SMB_SELFPACK, ext_desc, filepath);
		smb_freefilemem(&f);
		if(result != SMB_SUCCESS)
			fprintf(stderr, "!ERROR %d (%s) writing to %s\n"
				, result, smb.last_error, smb.file);
423
424

		if(mode&UL_STATS)
425
			updatestats((ulong)l);
426
		files++;
427
	} while(!feof(stream) && !ferror(stream));
428
429
430
	fclose(stream);
	if(mode&DEL_LIST && !(mode&SYNC_LIST)) {
		printf("\nDeleting %s\n",listpath);
431
		remove(listpath);
432
	}
433
434
	smb_close(&smb);
	strListFree(&fname_list);
435
436
437
438
}

void synclist(char *inpath, int dirnum)
{
439
	char	str[1024];
440
	char	listpath[MAX_PATH+1];
441
	char*	p;
442
443
	int		found;
	long	l;
444
	FILE*	stream;
445
446
447
	file_t*	f;
	file_t*	file_list;
	smb_t	smb;
448

449
	SAFECOPY(listpath,inpath);
450
	if((stream=fopen(listpath,"r"))==NULL) {
451
452
		sprintf(listpath,"%s%s",cur_altpath ? scfg.altpath[cur_altpath-1]
				: scfg.dir[dirnum]->path,inpath);
453
		if((stream=fopen(listpath,"r"))==NULL) {
454
455
			printf("Can't open: %s\n"
				   "        or: %s\n",inpath,listpath);
456
457
			return;
		}
458
	}
459

460
461
462
463
464
465
466
467
	int result = smb_open_dir(&scfg, &smb, dirnum);
	if(result != SMB_SUCCESS) {
		fprintf(stderr, "!Error %d (%s) opening %s\n", result, smb.last_error, smb.file);
		return;
	}
	size_t file_count;
	file_list = loadfiles(&smb, NULL, 0, /* extdesc: */FALSE, FILE_SORT_NATURAL, &file_count);

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

471
472
	for(l = 0; l < (long)file_count; l++) {
		f = &file_list[l];
473
474
475
476
477
478
		rewind(stream);
		found=0;
		while(!found) {
			if(!fgets(str,1000,stream))
				break;
			truncsp(str);
479
			p=strchr(str,' ');
480
			if(p) *p=0;
481
482
			if(!stricmp(str, f->name))
				found=1; 
483
		}
484
485
		if(found)
			continue;
486
487
488
489
490
491
492
493
		printf("%s not found in list - ", f->name);
		if(smb_removefile(&smb, f) != SMB_SUCCESS)
			fprintf(stderr, "!ERROR (%s) removing file from database\n", smb.last_error);
		else {
			if(remove(getfilepath(&scfg, f, str)))
				printf("Error removing %s\n",str);
			removed++;
			printf("Removed from database\n");
494
495
		}
	}
496
	freefiles(file_list, file_count);
497
498
499

	if(mode&DEL_LIST) {
		printf("\nDeleting %s\n",listpath);
500
		remove(listpath);
501
	}
502
	smb_close(&smb);
503
	fclose(stream);
504
505
}

506
char *usage="\nusage: addfiles code [.alt_path] [-opts] +list "
507
			 "[desc_off] [size_off]"
508
	"\n   or: addfiles code [.alt_path] [-opts] file "
509
		"[\"description\"]\n"
510
	"\navailable opts:"
511
512
513
514
515
516
	"\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"
517
	"\n      -F <fmt>   include file date in descriptions, using strftime format"
518
519
520
521
	"\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
522
	"\n      -p         compare file date with upload date for existing files"
523
524
525
526
527
528
	"\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)"
529
	"\n"
530
531
	"\nAuto-ADD:   use - in place of code for Auto-ADD of FILES.BBS"
	"\n            use -filename to Auto-ADD a different filename"
532
	"\n            use -l \"libname\" to only Auto-ADD files to a specific library"
533
534
535
536
537
538
539
540
	;

/*********************/
/* Entry point (duh) */
/*********************/
int main(int argc, char **argv)
{
	char error[512];
541
542
	char str[MAX_PATH+1];
	char tmp[MAX_PATH+1];
543
	char *p;
544
	char exist,listgiven=0,namegiven=0,ext[LEN_EXTDESC + 1]
545
		,auto_name[MAX_PATH+1]="FILES.BBS";
546
	int i,j;
547
	uint desc_offset=0, size_offset=0;
548
	long l;
549
	smb_t	smb;
550
	file_t	f;
551
	uint dirnum = INVALID_DIR;
552

553
	fprintf(stderr,"\nADDFILES v%s-%s %s/%s - Adds Files to Synchronet "
554
555
556
		"Filebase\n"
		,ADDFILES_VER
		,PLATFORM_DESC
557
558
		,GIT_BRANCH
		,GIT_HASH
559
560
561
		);

	if(argc<2) {
562
		puts(usage);
563
		return(1);
564
	}
565

566
	p = get_ctrl_dir(/* warn: */true);
567

568
569
	memset(&scfg,0,sizeof(scfg));
	scfg.size=sizeof(scfg);
570
	SAFECOPY(scfg.ctrl_dir,p);
571
572
573
574
575

	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);
576
	if(!load_cfg(&scfg, /* text: */NULL, /* prep: */TRUE, /* node: */FALSE, error, sizeof(error))) {
577
578
579
		fprintf(stderr,"!ERROR loading configuration files: %s\n",error);
		exit(1);
	}
rswindell's avatar
rswindell committed
580
581
	SAFECOPY(scfg.temp_dir,"../temp");
	prep_dir(scfg.ctrl_dir, scfg.temp_dir, sizeof(scfg.temp_dir));
582
	memset(&smb, 0, sizeof(smb));
583

584
585
	if(argv[1][0]=='*' || argv[1][0]=='-') {
		if(argv[1][1]=='?') {
586
			puts(usage);
587
588
			exit(0);
		}
589
		if(argv[1][1])
590
			SAFECOPY(auto_name,argv[1]+1);
591
		mode|=AUTO_ADD;
592
		i=0;
593
	} else {
594
		if(!IS_ALPHANUMERIC(argv[1][0]) && argc==2) {
595
			puts(usage);
596
			return(1);
597
598
		}

599
		for(i=0;i<scfg.total_dirs;i++)
600
			if(!stricmp(scfg.dir[i]->code,argv[1])) /* use matchmatchi() instead? */
601
602
603
604
				break;

		if(i>=scfg.total_dirs) {
			printf("Directory code '%s' not found.\n",argv[1]);
605
606
607
			exit(1); 
		} 
		dirnum = i;
608
	}
609

610
611
	memset(&f,0,sizeof(f));
	const char* uploader = "-> ADDFILES <-";
612
613

	for(j=2;j<argc;j++) {
614
		if(argv[j][0]=='*')     /* set the uploader name (legacy) */
615
616
			uploader = argv[j]+1;
		else 
617
618
619
			if(argv[j][0]=='-'
			|| argv[j][0]=='/'
			) {      /* options */
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
			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;
640
641
642
					case 'L':
						j++;
						if(argv[j]==NULL) {
643
							puts(usage);
644
645
646
647
648
							return(-1);
						}
						SAFECOPY(lib,argv[j]);
						i=strlen(argv[j])-1;
						break;
649
650
651
					case 'X':
						j++;
						if(argv[j]==NULL) {
652
							puts(usage);
653
654
							return(-1);
						}
655
						uploader = argv[j];
656
657
						i=strlen(argv[j])-1;
						break;
658
659
660
661
662
663
664
665
666
667
668
669
					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
670
671
672
					case 'P':
						mode|=CHECK_DATE;
						break;
673
674
675
676
677
					case 'U':
						mode|=NO_NEWDATE;
						break;
					case 'F':
						mode|=FILE_DATE;
678
679
680
681
682
683
684
685
686
687
						if(argv[j][i] == 'F') {
							j++;
							if(argv[j]==NULL) {
								puts(usage);
								return(-1);
							}
							datefmt = argv[j];
							i=strlen(argv[j]) - 1;
							break;
						}
688
689
690
691
692
693
694
695
						break;
					case 'T':
						mode|=TODAYS_DATE;
						break;
					case 'S':
						mode|=SEARCH_DIR;
						break;
					default:
696
						puts(usage);
697
698
						return(1);
			}
699
		}
700
		else if(IS_DIGIT(argv[j][0])) {
701
702
703
704
705
706
			if(desc_offset==0)
				desc_offset=atoi(argv[j]);
			else
				size_offset=atoi(argv[j]);
			continue;
		}
707
708
		else if(argv[j][0]=='+') {      /* filelist - FILES.BBS */
			listgiven=1;
rswindell's avatar
rswindell committed
709
			if(argc > j+1
710
				&& IS_DIGIT(argv[j+1][0])) { /* skip x characters before description */
rswindell's avatar
rswindell committed
711
				if(argc > j+2
712
					&& IS_DIGIT(argv[j+2][0])) { /* skip x characters before size */
713
					addlist(argv[j]+1, dirnum, uploader, atoi(argv[j+1]), atoi(argv[j+2]));
714
					j+=2;
715
				}
716
				else {
717
718
719
					addlist(argv[j]+1, dirnum, uploader, atoi(argv[j+1]), 0);
					j++; 
				} 
720
			}
721
			else
722
				addlist(argv[j]+1, dirnum, uploader, 0, 0);
723
			if(mode&SYNC_LIST)
724
				synclist(argv[j]+1, dirnum); 
725
		}
726
727
728
729
		else if(argv[j][0]=='.') {      /* alternate file path */
			cur_altpath=atoi(argv[j]+1);
			if(cur_altpath>scfg.altpaths) {
				printf("Invalid alternate path.\n");
730
731
				exit(1);
			}
732
		}
733
734
		else {
			namegiven=1;
735
736
737
			const char* fname = argv[j];
			char fdesc[LEN_FDESC + 1] = {0};

738
			if(j+1==argc) {
739
740
				printf("%s no description given.\n",fname);
				SAFECOPY(fdesc, "no description given");
741
			}
742

743
			sprintf(str,"%s%s",cur_altpath ? scfg.altpath[cur_altpath-1]
744
745
746
747
748
749
750
751
				: scfg.dir[dirnum]->path, fname);
			if(mode&FILE_DATE)
				sprintf(fdesc, "%s  ", unixtodstr(&scfg,(time32_t)fdate(str),tmp));
			if(mode&TODAYS_DATE)
				sprintf(fdesc, "%s  ", unixtodstr(&scfg,time32(NULL),tmp));
			sprintf(tmp, "%.*s", (int)(LEN_FDESC-strlen(fdesc)), argv[++j]);
			SAFECOPY(fdesc, tmp);
			l=(long)flength(str);
752
753
			if(l==-1) {
				printf("%s not found.\n",str);
754
				continue;
755
			}
756
757
758
759
760
761
762
763
764
765
			if(SMB_IS_OPEN(&smb))
				smb_close(&smb);

			int result = smb_open_dir(&scfg, &smb, dirnum);
			if(result != SMB_SUCCESS) {
				fprintf(stderr, "!ERROR %d (%s) opening %s\n", result, smb.last_error, smb.file);
				exit(EXIT_FAILURE);
			}

			exist = smb_findfile(&smb, fname, &f) == SMB_SUCCESS;
766
767
768
			if(exist) {
				if(mode&NO_UPDATE)
					continue;
769
				if((mode&CHECK_DATE) && fdate(str) <= f.idx.time)
770
					continue;
771
				if(mode&ULDATE_ONLY) {
772
773
774
					reupload(&smb, &f);
					continue; 
				} 
775
			}
776
777
			memset(&f, 0, sizeof(f));
			prep_file_desc(fdesc, fdesc);
778
			if(mode&ASCII_ONLY)
779
780
781
782
783
784
785
786
787
788
789
				strip_exascii(fdesc, fdesc);
			smb_hfield_str(&f, SMB_FILENAME, fname);
			smb_hfield_str(&f, SMB_FILEDESC, fdesc);
			smb_hfield_str(&f, SENDER, uploader);
			uint32_t cdt = (uint32_t)l;
			smb_hfield_bin(&f, SMB_COST, cdt);

			printf("%s %7"PRIu64" %s\n",fname, (int64_t)l, fdesc);
			char* ext_desc = NULL;
			if(get_file_diz(&f, ext, sizeof(ext)))
				ext_desc = ext;
790
791
			if(exist) {
				if(!(mode&NO_NEWDATE))
792
793
794
					reupload(&smb, &f);
				else
					result = smb_updatemsg(&smb, &f);
795
			}
796
			else
797
				result = smb_addfile(&smb, &f, SMB_SELFPACK, ext_desc, str);
798
799
			if(mode&UL_STATS)
				updatestats(l);
800
801
			files++;
		}
802
	}
803
804
805

	if(mode&AUTO_ADD) {
		for(i=0;i<scfg.total_dirs;i++) {
806
807
			if(lib[0] && stricmp(scfg.lib[scfg.dir[i]->lib]->sname,lib))
				continue;
808
809
			if(scfg.dir[i]->misc&DIR_NOAUTO)
				continue;
810
			dirnum = i;
811
			if(mode&SEARCH_DIR) {
812
813
				addlist("", dirnum, uploader, desc_offset, size_offset);
				continue; 
814
			}
815
			sprintf(str,"%s%s.lst",scfg.dir[dirnum]->path,scfg.dir[dirnum]->code);
816
			if(fexistcase(str) && flength(str)>0L) {
817
				printf("Auto-adding %s\n",str);
818
				addlist(str, dirnum, uploader, desc_offset, size_offset);
819
820
				if(mode&SYNC_LIST)
					synclist(str,i);
821
				continue;
822
			}
823
			SAFEPRINTF2(str,"%s%s",scfg.dir[dirnum]->path,auto_name);
824
			if(fexistcase(str) && flength(str)>0L) {
825
				printf("Auto-adding %s\n",str);
826
				addlist(str, dirnum, uploader, desc_offset, size_offset);
827
828
				if(mode&SYNC_LIST)
					synclist(str,i);
829
830
831
				continue;
			}
		}
832
	}
833
834
835

	else {
		if(!listgiven && !namegiven) {
836
			sprintf(str,"%s%s.lst",scfg.dir[dirnum]->path, scfg.dir[dirnum]->code);
837
			if(!fexistcase(str) || flength(str)<=0L)
838
				SAFEPRINTF2(str,"%s%s",scfg.dir[dirnum]->path, auto_name);
839
			addlist(str, dirnum, uploader, desc_offset, size_offset);
840
			if(mode&SYNC_LIST)
841
				synclist(str, dirnum);
842
		}
843
	}
844
845
846
847
848
849
850
851

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