#include "defs.h"

Prototype CheckDosStruct();
Prototype explore(WORD bloc,WORD parent);
Prototype CheckHeader(struct DiskList *dlist);
Prototype CheckFList(WORD bloc,WORD fhb);
Prototype CheckLink(WORD dataB,WORD fhB);
Prototype badFile(BYTE *adrName);
Prototype NotSet(WORD bloc,WORD where);

CheckDosStruct()
{
struct DiskList *dlist;
WORD n;
struct RootB *adr;
BYTE val;

	dlist=whereB(880);
	if (dlist==0) NotSet(880,880);
	else


	{	adr=(struct RootB *)dlist->dl_AdrB;
		for (n=0;n<72;n++) /* 72 compris puisque n++ */
		{
			if (val=explore(adr->HashTable[n],880))
			{
				if (val==1) exit(0);
				if (val==2) return(2);
			}
		}
	}
}

/*	explore: suit une chaine de Hash à partir du bloc header en paramètre */

explore(bloc,parent)
WORD bloc;
WORD parent;
{
struct DiskList *dlist; 
WORD n,nextbloc;
struct UserDirB *adr;
BYTE val;

	if (bloc==0) return(0);
	val=HandleIDCMP2(FOWin);
	if (val==2) return(val);
	/*printf("dans explore bloc: %d, parent: %d\n",bloc,parent);*/
	dlist=VarAdr->disklist;
	while (dlist->dl_Bloc!=bloc && dlist!=0)		dlist=dlist->dl_NextB;

	if (dlist==0) NotSet(bloc,parent);
	else

	if (dlist->dl_Type!=-1 && dlist->dl_Type!=4)
	{
		fprintf (FPointer,"ERR : Block #%d SHOULD BE Header or UserDir block\n",bloc);
		err++;
	}

	if (dlist->dl_types.dl_type4.dl_Parent!=parent)
	{
		fprintf(FPointer,"ERR : Link Error between block #%d and #%d\n",bloc,parent);
		err++;
	}

	if (dlist->dl_Type==-1) CheckHeader(dlist);
	if (dlist->dl_Type==4) 
	{
		adr=(struct UserDirB *)dlist->dl_AdrB;
		for (n=0;n<72;n++)
		{
			if (val=explore(adr->HashTable[n],bloc))
			{
				if (val==1) exit(0);
				if (val==2) return(2);
			}
		}
	}

	if (nextbloc=dlist->dl_types.dl_type1.dl_NextHash==0) return(0);
	else explore(nextbloc,parent);
}

CheckHeader(dlist)
struct DiskList *dlist;
{
WORD bloc,n;
struct FileHeaderB *adr;
BYTE errfile=0;

	bloc=dlist->dl_Bloc;
	/*printf("dans CheckHeader bloc: %d\n",bloc);*/
	adr=dlist->dl_AdrB;

	if (FFS==0)
	{
		for (n=0;n<72;n++)
		{
			errfile+=CheckLink(adr->DataTable[n],bloc);
		}
	}
	if (adr->Extension) CheckFList(adr->Extension,bloc);
	

	if (errfile) badFile(adr->FileName);
	return(0);
}
CheckFList(bloc,fhb)
WORD bloc,fhb;
{
struct SFileListB *dlistFL;
struct FileListB  *adr;
BYTE   errfile=0;
WORD   n;

	dlistFL=whereB(bloc);
/*	printf("dans CheckFList bloc: %d, pour FHB: %d\n",bloc,fhb);*/
	if (dlistFL==0) NotSet(bloc,fhb);
	else{
	if (dlistFL->dl_Type!=13)
	{
		fprintf(FPointer,"ERR : Block #%d SHOULD BE FileList block\n",bloc);
		err++;
		errfile++;
	}
	else
	{
		adr=(struct FileListB *)dlistFL->dl_AdrB;
		if (adr->ParentFH!=fhb)
		{
			fprintf(FPointer,"ERR : Link Error between block #%d and #%d\n",bloc,fhb);
			err++;
		}
		if (FFS==0)
		{
			for (n=0;n<72;n++)
			{
				errfile+=CheckLink(adr->DataTable[n],fhb);
			}
		}
	}
	if (adr->Extension) errfile+=CheckFList(adr->Extension,fhb);
	}
	return(errfile);
}

CheckLink(dataB,fhB)
WORD dataB,fhB;
{
struct SDataB *dlist;
BYTE errdata=0;

	if (dataB==0) return(0);
/*	printf("dans CheckLink data : %d, fh : %d\n",dataB,fhB);*/
	dlist=(struct SDataB *)VarAdr->disklist;
	while (dlist->dl_Bloc!=dataB && dlist!=0)		dlist=dlist->dl_NextB;

	if (dlist==0) NotSet(dataB,fhB);
	else

	if (dlist->dl_Type!=8)
	{
		fprintf(FPointer,"ERR : Block #%d SHOULD BE data block (pointed by FHB #%d)\n",dataB,fhB);
		err++;
		errdata=1;
	}
	else
	if (dlist->dl_type8.dl_FileHeader!=fhB)
	{
		fprintf(FPointer,"ERR : Link Error between block #%d and #%d\n",fhB,dataB);
		err++;
		errdata=1;
	}
	return(errdata);
}

badFile(adrName)
BYTE *adrName;
{
BYTE length;
BYTE buff[30];

	length=*adrName;
	adrName++;
	strncpy(buff,adrName,length);
	buff[length]=0;
	buff[length+1]='I';
	
	fprintf(FPointer,"File %s contains errors\n",buff);
}

NotSet(bloc,where)
WORD bloc,where;
{
	fprintf(FPointer,"Block #%d Not Found ! (not unset in BitMap), in #%d\n",bloc,where);
	err++;
}
