/****h* MiniBackup/mbackup.c [1.20] *
*
*  NAME
*    mbackup.c
*  COPYRIGHT
*    $VER: mbackup.c 1.20 (02.08.98) © by Stefan Kost 1997-1998
*  FUNCTION
*    backups files according to a taskfile using lha
*  AUTHOR
*    Stefan Kost
*  CREATION DATE
*    01.Aug.1998
*  MODIFICATION HISTORY
*    02.Aug.1998	V 1.20	extended args
*    05.Jan.1998	V 1.10	stack-bugs fixed
*    28.May.1997	V 1.00	first release
*    19.May.1997	V 0.00	initial version
*  NOTES
*    requires lha to be in dos path
*******
*/

//-- includes -----------------------------------------------------------------

//-- Ansi

#include <dos.h>
#include <math.h>
#include <mffp.h>				/* die entsprechenden Matheroutinen includen */
#include <mieeedoub.h>
#include <m68881.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

//-- AmigaOS

#include <exec/types.h>
#include <cmacros.h>
#include <dos/dos.h>
#include <dos/dostags.h>
#include <exec/exec.h>

#include <proto/dos.h>			/* Prototypes für Libraryfunctions */
#include <proto/exec.h>

//-- Local

#include "project.h"

//-- DebugTools

#define DEBUG_SRCPATH "sc:source/tagtools/puttag/"
#include <debug/dt_decl.h>

//-- prototypes ---------------------------------------------------------------

char *_stroserror(int errornum);
void Error(STRPTR fmt,...);
ULONG seekdir(FILE *wf,char *path,char *pat,UBYTE mode,ULONG nr);

//-- globals ------------------------------------------------------------------

UBYTE *VersTag="\0$VER:"PRJ_VERS;

#define ARG_TEMPLATE		"PATH/A,TASKFILE/A,COM=COMPLETE/S,INC=INCREMENTAL/S"
#define ARG_COUNT			4
#define ARGID_PATH			0
#define ARGID_TASKFILE		1
#define ARGID_COMPLETE		2
#define ARGID_INCREMENTAL	3

#define MODE_NONE			0
#define MODE_COMPLETE		1
#define MODE_INCREMENTAL	2

//-- externals ----------------------------------------------------------------

#pragma msg 72 ignore
extern long __near __stack=50000L;		/* reseve more stackspace; used by startup-code */
#pragma msg 72 warning

//-- definitions --------------------------------------------------------------

char *stroserror(int errornum)
{
	static char *deferr="unknown",*err;
	long i=0;

	err=deferr;
	while(i!=-1 && __os_errlist[i].errnum)
	{
		if(__os_errlist[i].errnum==errornum)
		{
			err=__os_errlist[i].msg;i=-1;
		}
		else i++;
	}
	return(err);
}

void Error(STRPTR fmt,...)
{
	va_list arglist;
	char str[256];
	int C_Error=errno;
	long IOError=IoErr();
	int OSError=_OSERR;

	va_start(arglist,fmt);
	printf(PRJ_NAME" : ");
	vprintf(fmt,arglist);
	if(C_Error) printf("\terrno : %s\n",strerror(C_Error));
	if(OSError) printf("\toserr : %s\n",stroserror(OSError));
	if(IOError) { Fault(IOError,"\tioerr ",str,255);printf("%s\n",str); }
	va_end(arglist);
}

ULONG seekdir(FILE *wf,char *path,char *pat,UBYTE mode,ULONG nr)
{
	struct FileLock *dirlock;
	struct FileInfoBlock InfoBlock;
	char newpath[256];

	MSG2("files=%5ld scanning %s",nr,path);
	if(dirlock=(struct FileLock *)Lock(path,SHARED_LOCK))
	{
		if(Examine((BPTR)dirlock,&InfoBlock))
		{
			if(InfoBlock.fib_DirEntryType>0 && InfoBlock.fib_DirEntryType!=3)	// it's a directory but no link
			{
				while(ExNext((BPTR)dirlock,&InfoBlock))
				{
					strmfp(newpath,path,InfoBlock.fib_FileName);
					if(InfoBlock.fib_DirEntryType<0)							// it's a file
					{
						if(mode==MODE_COMPLETE)										// if it matches the pattern then add to list
						{
							if(MatchPatternNoCase(pat,InfoBlock.fib_FileName)) { fprintf(wf,"%s\n",newpath);nr++; }
						}
						if(mode==MODE_INCREMENTAL)									// if it has changed & matches the pattern then add to list
						{
							if(!(InfoBlock.fib_Protection&FIBF_ARCHIVE))				// file has changed
							{
								if(MatchPatternNoCase(pat,InfoBlock.fib_FileName)) { fprintf(wf,"%s\n",newpath);nr++; }
							}
						}
					}
					else nr=seekdir(wf,newpath,pat,mode,nr);					// it's a directory
				}
			}
			else printf("ERROR: %s is no directory\n",path);
		}
		UnLock((BPTR)dirlock);
	}
	return(nr);
}

int main(int argc,char *argv[])
{
	struct RDArgs *rda;
	LONG args[ARG_COUNT]={0};
	char dest[256],ndate[20],odate[10],path[256],tpat[30],pat[100],cmdln[256];
	time_t t;
	struct tm *p;
	UBYTE nday,oday,nmon,omon;
	FILE *tf,*wf;
	UBYTE mode=MODE_NONE;			// default is - no backup
	UBYTE force=FALSE;				// default is - we check the date
	ULONG nr=0;
	int numRetVal=RETURN_OK;

	REPORT_CALLS;

	BREAK(PRJ_NAME" has been started");

	if(rda=ReadArgs(ARG_TEMPLATE,args,NULL))
	{
		time(&t);p=localtime(&t);					// get date & time
		strftime(ndate,9,"%Y%m%d",p);ndate[9]=0;
		strmfp(dest,(char *)args[ARGID_PATH],ndate);
		if(args[ARGID_COMPLETE]) 	{ force=TRUE;mode=MODE_COMPLETE; }		// force complete backup
		if(args[ARGID_INCREMENTAL])	{ force=TRUE;mode=MODE_INCREMENTAL; }	// force incremental backup
		if(!force)															// check date & time
		{
			if((wf=fopen("progdir:mbackup.last_backup","rb")))
			{
				fread(odate,9,1,wf);odate[9]=0;
				fclose(wf);
				nmon=(ndate[4]-48)*10+(ndate[5]-48);
				omon=(odate[4]-48)*10+(odate[5]-48);
				if(nmon>omon) mode=MODE_COMPLETE;		// first backup in new month)
				else
				{
					nday=(ndate[6]-48)*10+(ndate[7]-48);
					oday=(odate[6]-48)*10+(odate[7]-48);
					if(nday>=oday+7) mode=MODE_INCREMENTAL;
				}
			}
			else mode=MODE_COMPLETE;
		}
		MSG1("force backup : %d",force);
		MSG1("backup mode : %d",mode);
		MSG1("backup date : %s",ndate);
		if(mode)
		{
			if((wf=fopen("t:mbackup.tmp","wt")))
			{
				if((tf=fopen((char *)args[ARGID_TASKFILE],"rt")))
				{
					while(!feof(tf))					// build filelist
					{
						fscanf(tf,"%s %s",path,tpat);
						if(ParsePatternNoCase(tpat,pat,100)>=0)	nr=seekdir(wf,path,pat,mode,nr);
						else printf("ERROR: Wrong pattern %s\n",pat);
					}
					fclose(tf);
					fclose(wf);
					MSG1("%d files to backup",nr);
					if(nr>0)							// if there are files to backup,
					{									// invoke lha
						if(mode==MODE_COMPLETE) sprintf(cmdln,"lha -it:mbackup.tmp -q -x -S a %sc\n",dest);
						if(mode==MODE_INCREMENTAL) sprintf(cmdln,"lha -it:mbackup.tmp -q -x -S a %si\n",dest);
						SystemTags(cmdln,SYS_Asynch,FALSE,SYS_Output,Output(),SYS_Input,Input());
					}
					DeleteFile("t:mbackup.tmp");
					MSG("lha finished");
					
					if(mode==MODE_COMPLETE) sprintf(cmdln,"%sc.lha",dest);
					if(mode==MODE_INCREMENTAL) sprintf(cmdln,"%si.lha",dest);
					if((tf=fopen(cmdln,"rt")))			// hat lha geklappt ?
					{
						fclose(tf);
						MSG("now saving status");
						if((wf=fopen("progdir:mbackup.last_backup","wb")))
						{
							time(&t);p=localtime(&t);							// something is scrambling that field
							strftime(ndate,9,"%Y%m%d",p);ndate[9]=0;			// so I've to set this again
							fwrite(ndate,9,1,wf);
							fclose(wf);
						}
						if((wf=fopen("progdir:mbackup.log","at")))
						{
							strftime(ndate,20,"%d.%m.%Y",p);
							if(mode==MODE_COMPLETE) fprintf(wf,"Complete backup on %s\n",ndate);
							if(mode==MODE_INCREMENTAL) fprintf(wf,"Incremental backup on %s\n",ndate);
							fclose(wf);
						}
					}
				}
				else
				{
					fclose(wf);
					Error("open taskfile \"%s\"\n",args[ARGID_TASKFILE]);numRetVal=RETURN_ERROR;
				}
			}
			else { Error("open workfile \"t:mbackup.tmp\"\n");numRetVal=RETURN_ERROR; }
		}
		FreeArgs(rda);															// free args
	}
	else { printf("Usage : "PRJ_NAME" %s\n",ARG_TEMPLATE);numRetVal=RETURN_WARN; }

	BREAK(PRJ_NAME" is ready");

	REPORT_OFF;

	return(numRetVal);
}

//-- eof ----------------------------------------------------------------------
