#include <exec/types.h>
#include <exec/memory.h>
#include <exec/execbase.h>

#include <dos/dos.h>
#include <dos/rdargs.h>

#include <proto/dos.h>
#include <proto/exec.h>

#include "FindDup_rev.h"


const UBYTE VerStr[] = VERSTAG;
#define INFO "›33m" VERS "›0m (c) 1997 LeMUr/blabla\n\n"


UBYTE *Bufor;
BOOL found = FALSE;

// parametry wywoîania
#define TEMPLATE	"FILE/A,DIR"
#define ARG_FILE	0
#define ARG_DIR	1
#define ARG_COUNT	2


long Check(UBYTE *);
void FindBySize(UBYTE *, ULONG);
void Show(UBYTE *, UBYTE *);
BOOL LoadFile(UBYTE *, ULONG, UBYTE **, ULONG *);
void StrCpy(UBYTE *, UBYTE *);


struct ExecBase *SysBase;
struct DosLibrary *DOSBase;


ULONG __saveds main(void)
{
	ULONG size;

	struct RDArgs *args = NULL;
	UBYTE file[256], dir[256];
	LONG argsarray[ARG_COUNT] = {0, 0};


	SysBase = *((struct ExecBase **) 4L);
	if(SysBase->LibNode.lib_Version < 37)
		return RETURN_FAIL;

	if(!(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 37)))
		return RETURN_FAIL;

	if(!(args = (struct RDArgs *)ReadArgs(TEMPLATE, argsarray, NULL)))
	{
		PrintFault(IoErr(), "FindDup");
		CloseLibrary((struct Library *)DOSBase);
		return RETURN_FAIL;
	}

	PutStr(INFO);


	// kopiowanie argumentów
	StrCpy(file, (UBYTE *)(argsarray[ARG_FILE]));
	if(argsarray[ARG_DIR])
		StrCpy(dir, (UBYTE *)(argsarray[ARG_DIR]));
	else
		GetCurrentDirName(dir, 256);


	// caîy czar tutaj ;)
	if(LoadFile(file, MEMF_ANY, &Bufor, &size))
	{
		FindBySize(dir, size);
		FreeMem(Bufor, size);
	}
	else
		PrintFault(IoErr(), "FindDup");

	if(!found)
		Printf("Nothing found!\n");

	FreeArgs(args);
	return RETURN_OK;
}


void FindBySize(UBYTE *start_dir, ULONG fsize)
// rekursyjne szukanie pliku o podanym rozmiarze
{
	BPTR lock;
	struct FileInfoBlock *fib;
	UBYTE temp_name[256];

	if(fib = AllocDosObject(DOS_FIB, NULL))
	{
		if(lock = Lock(start_dir, SHARED_LOCK))
		{
			if(Examine(lock, fib))
			{
				while(ExNext(lock, fib))
				{
					if(fib->fib_Size == fsize)
						Show(start_dir, fib->fib_FileName);

					// jeôli podkatalog to teű go sprawdú
					if(fib->fib_DirEntryType > 0)
					{
						StrCpy(temp_name, start_dir);
						AddPart(temp_name, fib->fib_FileName, 256);
						FindBySize(temp_name, fsize);
					}
				}
			}
			UnLock(lock);
		}
		FreeDosObject(DOS_FIB, fib);
	}
}


void Show(UBYTE *fdir, UBYTE *fname)
{
	UBYTE temp_name[256];

	StrCpy(temp_name, fdir);
	AddPart(temp_name, fname, 256);

	if(Check(temp_name))					// czy pliki jednakowe?
	{
		Printf("%s\n", temp_name);
		found = TRUE;
	}
}


long Check(UBYTE *filename)
// porównanie plików
{
	long same = TRUE;
	UBYTE *buf_file;
	ULONG len, i;

	if(LoadFile(filename, MEMF_ANY, &buf_file, &len))
	{
		// pëtla porównujâca
		for(i = 0; i != len; i++)
			if(Bufor[i] != buf_file[i])
				same = FALSE;
		FreeMem(buf_file, len);
	}
	else
		same = FALSE;

	return same;
}


BOOL LoadFile(UBYTE *fname, ULONG mem_type, UBYTE **memory, ULONG *flen)
{
	UBYTE *temp_mem;
	ULONG temp_len;

	BPTR file, lock;
	struct FileInfoBlock __aligned fib;

	BOOL retval = FALSE;

	if(lock = Lock(fname, ACCESS_READ))
	{
		if(Examine(lock, &fib))
		{
			if(temp_len = fib.fib_Size)
			{
				if(temp_mem = AllocMem(temp_len, mem_type))
				{
					if(file = Open(fname, MODE_OLDFILE))
					{
						Read(file, temp_mem, temp_len);
						Close(file);
						retval = TRUE;
					}
				}
			}
		}
		UnLock(lock);
	}

	*memory = temp_mem;
	*flen = temp_len;
	return retval;
}


void StrCpy(UBYTE *dest, UBYTE *src)
// wîasne kopiowanie ciâgów - zaoszczëzenie rozmiarów w wynikówce
{
	ULONG i = 0;

	while(src[i])
	   dest[i] = src[i++];

	dest[i] = 0;				// zabezpiecznie ;)
}
