// FOR LAW ENFORCEMENT USE ONLY
// Pseudo Code for fatback
// By SrA Nicholas Harbour
// 
// the "//" denotes a comment, and a "\" denotes a statement is 
// continued on the following line

//---Program begins here-------
Start out by assuming that the input stream is raw disk
If SanityCheck_MBR() turns out ok:
	call Undelete_partition() for each partition
If the sanity check failed:
	assume its a partition and call Undelete_partition()
		//assuming that routine
		//will check the integrity of
		//the VBR 	
//--------------------------------------------------

Undelete_partition():
	Call SanityCheck_VBR() to make sure this is valid partition
	If the input stream was a raw disk:
		Assume FS ID is as reported in the MBR
		Call Determine_FSID() to verify the partition type
			//this call is used for auditing purposes
			//the FS ID byte in the MBR will be the 
			//determining factor	
	Else:
		Call Determine_FSID() to find out which FS type it is
		//Since no MBR is present, this call will attempt to
		//guess which FS is present.
	
	Store the FAT into memory
	Create a Bitmap of clusters in memory
	
	//PHASE 1
	Walk the logical directory structure
		if it is a directory:
			store its information in the list of directories
		if it is part of a long file name:
			convert wide character string to single byte characters
			store string with seqence number and reference to dir in\
			the list of lfn fragments
		if a file is active:
			if the filesize is too small for the number\
			of clusters occupied:
				add the erronious clusters to the lost\
				cluster chain list.
				flag the proper clusters in the bitmap
			else:
				flag its clusters in the bitmap
		else if a file is deleted:
			add its information to the list of deleted files
				
	//PHASE 2
	Scan through all remaining free clusters
		Determine if the cluster is a directory by calling dir_check()
		if it was a directory:
			Goto the Recover_directory() section
	Scan through all FAT entries
		if the cluster pointed to by the FAT entry is not active:
			recover_lost_chain()

	//PHASE 3
	Corrilate long filenames to files and dir's
	Using the list of deleted files created in the previous step,
		determine if there are multiple entries pointing to\
		the same cluster chain,
		if duplicate chain references:
			determine which is newer and add it\
			to the tree of files to recover 
		if unique:
			add it to the tree of files to recover
	Using the list of deleted directories,
		If a deleted file reports the same clusters as a deleted dir,
			discard the directory and leave the file
		If a directory has a deleted directory as an entry,
			attempt to find that directory in the list and\
			add it as a branch off of this directory
	
	//PHASE 4
	Using the tree of deleted directories prepared in phase 3,
		parse through each directory and call recover() on any\
		file as well as create each directory if it contains deleted\
		files.
	Using the remaining list of directories that could not be fitted\
	into the logical tree,
		if the dir contains any deleted files create the directory\
		off of the "unknown" subdir
		call recover() on any deleted files 			
//-------------------------------------------------------------------		

Recover_directory():
	Determine if cluster chain is a valid directory
	if it is valid:
		add its info to the list of deleted directories
		then for each entry in the directory:
			Call SanityCheck_dir_entry()
			if it is a directory:
				call Recover_directory() on it
			if it is a file:
				store its info in the list of deleted files
//--------------------------------------------------


SanityCheck_MBR():
	Check to make sure that:
		the first byte of each partition entry is either x80 or 0
		the filesystem ID is an acceptable one
		the partition boundries dont overlap
		ends with 0x55AA
//----------------------------------------------------


SanityCheck_VBR():
	Check to make sure that:
		all 8 bytes of the OEM name are ascii characters
		sectors per cluster is a power of 2
		FAT copes nonzero  //maybe <= 2?
		Media descriptor byte is legal //maybe just nonzero?
		The number of reserved sectors is > 0 //or explicitly 1
		Volume serial number is non-null
		Volume label is ASCII readable
		(total sectors if > 32mb) field  and (total sectors if <=32mb)\
			 field are mutually exclusive
		ends with 0x55AA
//---------------------------------------------------
		

recover():
	Starting with the first cluster in the cluster chain:
		if the cluster is free in the cluster bitmap:
			extract that cluster
			continue loop using the next cluster in the chain
		else:
			quit the loop
//------------------------------------------------

dir_check():
	Check to make sure that:
		it begins with a "." followed by 10 spaces
		the next entry is a ".." followed by 9 spaces
		//Note: this method wont detect a deleted root dir
		//on the odd occasion of that occuring manual
		//recovery would be needed.  might be a nifty 
		//feature to add to a later version, but not 
		//necessary yet.
		
//----------------------------------------------
Determine_FSID():
	If the partition is < 16mb then it is FAT12
	If it is > 16mb and < 512mb then it is FAT16
	If it is > 2gb then it is FAT32
	If it is > 512mb and < 2gb:
		compare the size of the FAT with the number of clusters
		the size of each FAT entry
	
//---------------------------------------------
SanityCheck_dir_entry():
	Check to make sure that:
		All 11 bytes of the filename are legal
		The first 8 bytes of the filename contain at\
		least one non whitespace character.
		If the attribs are RSHV and the cluster number is 0
		(even if filename is illegal)
			then assume it is part of a Long file name
		Starting cluster number is within valid range of FAT type
		the attributes are valid
		size is withing range of partition and FS limits
