///////////////////////////////////////////////////////////////////////////////
/// @file deFSReal.cpp
///
/// @brief real file system interface
///
/// @author Lightning
///
/// This file is the intellectual property of Novus Delta, LLC.. Usage of the
/// contents of this file is subject to the Destiny3D Member License which
/// can be found at http://www.destiny3d.com.  Any other usage is prohibited.
///
/// This file is distributed "AS IS" without warranty of any kind.  Novus
/// Delta, LLC. does not guarantee the fitness of the contents of this file
/// for any particular purpose.
///
/// Copyright (C) 2001-2003 Novus Delta, LLC. All Rights Reserved.
///
/// <hr>
///                                 Change History
/// <hr>
///
/// @date Nov 2001
/// @author Lightning
/// @remarks Creation
///
/// @date Apr 2002
/// @author Lightning
/// @remarks Renamed from deFSDos to deFSReal
///
/// @date Dec 2002
/// @author kurifu
/// @remarks Added find handles
///
/// @date May 2003
/// @author Lightning
/// @remarks Split apart between file and file system
///
///////////////////////////////////////////////////////////////////////////////

#ifdef _WIN32
//#include <windows.h>
#elif linux
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fnmatch.h>
#include <cstdio>
#include <cassert>
#endif

#include "deFileSystem_priv.hpp"
#include "deFile_priv.hpp"

//critial section object to keep deFSReal systems from changing directories on each other
#ifdef _WIN32
CRITICAL_SECTION	CriticalDirectory;
long			CriticalInit = 0;		//counter for number of initialized classes
#elif linux
pthread_mutex_t		CriticalDirectory = PTHREAD_MUTEX_INITIALIZER;
#endif

deFSReal::deFSReal()
{
#ifdef _WIN32
	//if the critical section isn't initialized, initialize it
	if(!CriticalInit)
		InitializeCriticalSection(&CriticalDirectory);

	//up the number one to tell it is initialized
	CriticalInit++;

	//get the current directory
	EnterCriticalSection(&CriticalDirectory);
	GetCurrentDirectory(sizeof(priv_CurrentDirectory), priv_CurrentDirectory);
	LeaveCriticalSection(&CriticalDirectory);

#elif linux
	// get the current directory
	pthread_mutex_lock(&CriticalDirectory);
	getcwd(priv_CurrentDirectory,sizeof(priv_CurrentDirectory));
	pthread_mutex_unlock(&CriticalDirectory);
#else
#error Initialization of deFSReal not written for OS
#endif
}

deFSReal::~deFSReal()
{
#ifdef _WIN32
	//decrement the critical init count
	CriticalInit--;

	//if no more critical init's then destroy the CriticalDirectory
	if(!CriticalInit)
		DeleteCriticalSection(&CriticalDirectory);
#elif linux
#else
#error Closing of deFSReal not written for OS
#endif

}

void* deFSReal::GetInterface(IdeFileSystem::interface_t i)
{
	if (i == IdeFileSystem::iface_IdeFileSystem)
		return (IdeFileSystem*)(this);
	if (i == IdeFileSystem::iface_IdeFSReal)
		return (IdeFSReal*)(this);
	return NULL;
}

IdeFile* deFSReal::Open(const char *Filename, long OpenFlags)
{
	//open up a file
	deFileReal *	NewFile;
	
	//create the new file class
	NewFile = new deFileReal;
	if(!NewFile)
		return NULL;

	//do our internal open
	if(!Open(NewFile, Filename, OpenFlags))
	{
		NewFile->Release();
		return NULL;
	}

	return NewFile;
}

deBoolean deFSReal::Open(deFileReal *RealFile, const char *Filename, long OpenFlags)
{
#ifdef _WIN32
	//open up a file
	DWORD			AccessFlags;
	DWORD			CreationFlags;
	
	//figure out the flags
	AccessFlags = 0;
	if(OpenFlags & deFile_Open_Read)
		AccessFlags = AccessFlags | GENERIC_READ;
	if(OpenFlags & deFile_Open_Write)
		AccessFlags = AccessFlags | GENERIC_WRITE;

	//figure out the creation flags
	CreationFlags = 0;
	switch(OpenFlags & 0x0000000F)
	{
		case deFile_Open_Create:
			//create new ones only
			CreationFlags = CREATE_NEW;
			break;


		case deFile_Open_Existing:
			//open only existing files
			CreationFlags = OPEN_EXISTING;
			break;

		case deFile_Open_Always:
			//always open it, even if it doesnt exist
			CreationFlags = OPEN_ALWAYS;
			break;

		case deFile_Open_CreateAlways:
			//always create it, even if it exists
			CreationFlags = CREATE_ALWAYS;
			break;

		default:
			return deFALSE;
	}

	//change the current directory
	EnterCriticalSection(&CriticalDirectory);
	GetCurrentDirectory(sizeof(priv_TempCurrentDirectory), priv_TempCurrentDirectory);
	SetCurrentDirectory(priv_CurrentDirectory);

	//open up the file
	RealFile->priv_FileHandle = CreateFile(Filename, AccessFlags, 0, NULL, CreationFlags, 0, NULL);

	//return the directory
	SetCurrentDirectory(priv_TempCurrentDirectory);
	LeaveCriticalSection(&CriticalDirectory);

#elif linux
	//open up a file
	DWORD			Flags;

	//figure out the flags
	Flags = 0;
	if(OpenFlags ==  deFile_Open_Read)
		Flags = O_RDONLY;
    else 	if(OpenFlags == deFile_Open_Write)
		Flags =  O_WRONLY;
    else Flags =  O_RDWR;

	//figure out the creation flags
	switch(OpenFlags & 0x0000000F)
	{
		case deFile_Open_Create:
			//create new ones only
			Flags |= O_CREAT | O_EXCL;
			break;      

		case deFile_Open_Existing:
			break;

		case deFile_Open_Always:
			//always open it, even if it doesnt exist
			Flags |= O_CREAT;
			break;

		case deFile_Open_CreateAlways:
			//always create it, even if it exists
			Flags |= O_CREAT | O_TRUNC;
			break;

		default:
			return deFALSE;
	}

	//change the current directory
  	pthread_mutex_lock(&CriticalDirectory);
	getcwd(priv_TempCurrentDirectory,sizeof(priv_TempCurrentDirectory));
	chdir(priv_CurrentDirectory);

	 //open up the file
    RealFile->priv_FileHandle = open(Filename,Flags,0666);
    strcpy(RealFile->priv_FilePath,priv_CurrentDirectory);
    strcat(RealFile->priv_FilePath,Filename);

	//return the directory
	chdir(priv_TempCurrentDirectory);
	pthread_mutex_unlock(&CriticalDirectory);
#else
#error File Opening not written for OS
#endif

	//see if it failed or not
	if((long)RealFile->priv_FileHandle == -1)
		return deFALSE;

	//copy the name
	memcpy(RealFile->priv_Filename, Filename, strlen(Filename) + 1);

	//set the actual flags
	RealFile->priv_OpenFlags = OpenFlags;

	return deTRUE;
}

const char *deFSReal::GetDirectory()
{
	//return the current directory
	return (char *)&priv_CurrentDirectory;
}

deBoolean deFSReal::SetDirectory(const char *Directory)
{
	//set the current directory

	//make sure the name isn't too long
	if(strlen(Directory) > 255)
		return deFALSE;

	//set it
	memcpy(priv_CurrentDirectory, Directory, strlen(Directory) + 1);
	return deTRUE;
}

deBoolean deFSReal::Rename(const char *OldFilename, const char *NewFilename)
{
#ifdef WIN32
	//rename a file
	BOOL	Ret;
  
	//change the current directory
	EnterCriticalSection(&CriticalDirectory);
	GetCurrentDirectory(sizeof(priv_TempCurrentDirectory), priv_TempCurrentDirectory);
	SetCurrentDirectory(priv_CurrentDirectory);

	//rename the file
	Ret = MoveFile(OldFilename, NewFilename);

	//return the directory
	SetCurrentDirectory(priv_TempCurrentDirectory);
	LeaveCriticalSection(&CriticalDirectory);

  	if(!Ret)
		return deFALSE;
    	
#elif linux
	//change the current directory
  	pthread_mutex_lock(&CriticalDirectory);
	getcwd(priv_TempCurrentDirectory,sizeof(priv_TempCurrentDirectory));
	chdir(priv_CurrentDirectory);

	 // Open the files
    int  OldFile = open(OldFilename,O_RDONLY);

    if(OldFile == -1)
    {
      close(OldFile);
      return deFALSE;
    }
    
    int  NewFile = open(NewFilename,O_WRONLY | O_CREAT | O_EXCL);
    if(NewFile == -1)
      return deFALSE;
      
    // Copy the file's permisions
    struct stat FileInfo;
    fstat(OldFile,&FileInfo);
    fchmod(NewFile,FileInfo.st_mode);

    int BytesRead = 0;
    const int BufferSize =  1024 * 64;
    void * Buffer = malloc(BufferSize);
    do
    {
      BytesRead = read(OldFile, Buffer,BufferSize);
      write(NewFile,Buffer,BytesRead);
    }
    while(BytesRead == BufferSize);

    free(Buffer);

    // Close the files
    close(NewFile);
    close(OldFile);

    // Delete the old file
    unlink(OldFilename);

  //return the directory
	chdir(priv_TempCurrentDirectory);
	pthread_mutex_unlock(&CriticalDirectory);

  return deTRUE;
  
#else
#error Renaming of files not written for OS
#endif
	return deTRUE;
}

deBoolean deFSReal::Delete(const char *Filename, deFSPROGRESS /*StatusCallback*/)
{
#ifdef WIN32       
  	//delete a file
	BOOL Ret;

  //change the current directory
	EnterCriticalSection(&CriticalDirectory);
	GetCurrentDirectory(sizeof(priv_TempCurrentDirectory), priv_TempCurrentDirectory);
	SetCurrentDirectory(priv_CurrentDirectory);

	//delete the file
	Ret = DeleteFile(Filename);

	//return the directory
	SetCurrentDirectory(priv_TempCurrentDirectory);
	LeaveCriticalSection(&CriticalDirectory);

  	if(!Ret)
		return deFALSE;
#elif linux
    int Ret;
    
	//change the current directory
   pthread_mutex_lock(&CriticalDirectory);
	getcwd(priv_TempCurrentDirectory,sizeof(priv_TempCurrentDirectory));
	chdir(priv_CurrentDirectory);

	//delete the file
   Ret =unlink(Filename);

 	//return the directory
	chdir(priv_TempCurrentDirectory);
	pthread_mutex_unlock(&CriticalDirectory);

   if(Ret == -1)
      return deFALSE;    
#else
#error Deletion of files not written for OS
#endif

	return deTRUE;
}

deBoolean deFSReal::Move(const char *OldFilename, const char *NewFilename, deFSPROGRESS /*StatusCallback*/)
{
#ifdef WIN32
	//move a file
	BOOL	Ret;
  
	//change the current directory
	EnterCriticalSection(&CriticalDirectory);
	GetCurrentDirectory(sizeof(priv_TempCurrentDirectory), priv_TempCurrentDirectory);
	SetCurrentDirectory(priv_CurrentDirectory);

	//move the file
	Ret = MoveFile(OldFilename, NewFilename);

	//return the directory
	SetCurrentDirectory(priv_TempCurrentDirectory);
	LeaveCriticalSection(&CriticalDirectory);


	if(!Ret)
		return deFALSE;
#elif linux
    int OldFile;
    int  NewFile;

	//change the current directory
  	pthread_mutex_lock(&CriticalDirectory);
	getcwd(priv_TempCurrentDirectory,sizeof(priv_TempCurrentDirectory));
	chdir(priv_CurrentDirectory);

	 // Open the files
    OldFile = open(OldFilename,O_RDONLY);
    if(OldFile == -1)
    {
      close(OldFile);
      return deFALSE;
    }

    if(NewFilename[strlen(NewFilename)-1] == '/' )
    {
      char NewFilePath[256];
      strcpy(NewFilePath,NewFilename);
      strcat(NewFilePath,OldFilename);
      NewFile = open(NewFilePath,O_WRONLY | O_CREAT | O_EXCL);
    }
    else
      NewFile = open(NewFilename,O_WRONLY | O_CREAT | O_EXCL);

    if(NewFile == -1)
      return deFALSE;

    // Copy the file's permisions
    struct stat FileInfo;
    fstat(OldFile,&FileInfo);
    fchmod(NewFile,FileInfo.st_mode);

    int BytesRead = 0;
    const int BufferSize =  1024 * 64;
    void * Buffer = malloc(BufferSize);
    do
    {
      BytesRead = read(OldFile, Buffer,BufferSize);
      write(NewFile,Buffer,BytesRead);
    }
    while(BytesRead == BufferSize);

    free(Buffer);

    // Close the files
    close(NewFile);
    close(OldFile);

    // Delete the old file
    unlink(OldFilename);
   
   //return the directory
	chdir(priv_TempCurrentDirectory);
	pthread_mutex_unlock(&CriticalDirectory);

  return deTRUE;     
#else
#error Moving a file not written for OS
#endif
	return deTRUE;
}

deBoolean deFSReal::Copy(const char *OldFilename, const char *NewFilename, deFSPROGRESS /*StatusCallback*/)
{
	//copy a file (we don't allow copying on top of other files)
	BOOL	Ret;

#ifdef WIN32

	//change the current directory
	EnterCriticalSection(&CriticalDirectory);
	GetCurrentDirectory(sizeof(priv_TempCurrentDirectory), priv_TempCurrentDirectory);
	SetCurrentDirectory(priv_CurrentDirectory);

	//copy the file
	Ret = CopyFile(OldFilename, NewFilename, TRUE);

	//return the directory
	SetCurrentDirectory(priv_TempCurrentDirectory);
	LeaveCriticalSection(&CriticalDirectory);
	
#elif linux
    int OldFile;
    int  NewFile;
    
	//change the current directory
  	pthread_mutex_lock(&CriticalDirectory);
	getcwd(priv_TempCurrentDirectory,sizeof(priv_TempCurrentDirectory));
	chdir(priv_CurrentDirectory);

	 // Open the files
    OldFile = open(OldFilename,O_RDONLY);
    if(OldFile == -1)
    {
      close(OldFile);
      return deFALSE;
    }

    if(NewFilename[strlen(NewFilename)-1] == '/' )
    {
      char NewFilePath[256];
      strcpy(NewFilePath,NewFilename);
      strcat(NewFilePath,OldFilename);
      NewFile = open(NewFilePath,O_WRONLY | O_CREAT | O_EXCL);
    }
    else
      NewFile = open(NewFilename,O_WRONLY | O_CREAT | O_EXCL);

    if(NewFile == -1)
      return deFALSE;
      
    // Copy the file's permisions
    struct stat FileInfo;
    fstat(OldFile,&FileInfo);
    fchmod(NewFile,FileInfo.st_mode);

    int BytesRead = 0;
    const int BufferSize =  1024 * 64;
    void * Buffer = malloc(BufferSize);
    do
    {
      BytesRead = read(OldFile, Buffer,BufferSize);
      write(NewFile,Buffer,BytesRead);
    }
    while(BytesRead == BufferSize);

    free(Buffer);

    // Close the files
    close(NewFile);
    close(OldFile);  

   //return the directory
	chdir(priv_TempCurrentDirectory);
	pthread_mutex_unlock(&CriticalDirectory);

  return deTRUE;     
#else
#error Copying a file not written for OS
#endif

	if(!Ret)
		return deFALSE;

	return deTRUE;
}

deBoolean deFSReal::AddDirectory(const char *Directory)
{
#ifdef WIN32
	//create a directory
	BOOL	Ret;
  
	//change the current directory
	EnterCriticalSection(&CriticalDirectory);
	GetCurrentDirectory(sizeof(priv_TempCurrentDirectory), priv_TempCurrentDirectory);
	SetCurrentDirectory(priv_CurrentDirectory);

	//create a directory
	Ret = CreateDirectory(Directory, NULL);

	//return the directory
	SetCurrentDirectory(priv_TempCurrentDirectory);
	LeaveCriticalSection(&CriticalDirectory);

 	if(!Ret)
		return deFALSE;

	return deTRUE;	
#elif linux
  int Ret;
  
	//change the current directory
  pthread_mutex_lock(&CriticalDirectory);
	getcwd(priv_TempCurrentDirectory,sizeof(priv_TempCurrentDirectory));
	chdir(priv_CurrentDirectory);

  // Create a directory
  Ret = mkdir(Directory,0777);

 	//return the directory
	chdir(priv_TempCurrentDirectory);
	pthread_mutex_unlock(&CriticalDirectory);

  if(Ret == -1)
    return deFALSE;
  return deTRUE;  
#else
#error Creation of a directory not written for OS
#endif
}

deBoolean deFSReal::DeleteDirectory(const char *Directory, deFSPROGRESS /*StatusCallback*/)
{
#ifdef WIN32
	//copy a file (we don't allow copying on top of other files)
	BOOL	Ret;

	//change the current directory
	EnterCriticalSection(&CriticalDirectory);
	GetCurrentDirectory(sizeof(priv_TempCurrentDirectory), priv_TempCurrentDirectory);
	SetCurrentDirectory(priv_CurrentDirectory);

	//delete a directory
	Ret = RemoveDirectory(Directory);

	//return the directory
	SetCurrentDirectory(priv_TempCurrentDirectory);
	LeaveCriticalSection(&CriticalDirectory); 

	if(!Ret)
		return deFALSE;

	return deTRUE;	
#elif linux
  int Ret;

	//change the current directory
  pthread_mutex_lock(&CriticalDirectory);
	getcwd(priv_TempCurrentDirectory,sizeof(priv_TempCurrentDirectory));
	chdir(priv_CurrentDirectory);

  // Delete a directory
  Ret = rmdir(Directory);

 	//return the directory
	chdir(priv_TempCurrentDirectory);
	pthread_mutex_unlock(&CriticalDirectory);

  if(Ret == -1)
    return deFALSE;
  return deTRUE;  
#else
#error Deletion of a directory not written for OS
#endif
}

#ifdef WIN32

void* deFSReal::FindFirst(const char *Pattern, deFileProperties *Properties)
{
	FindInfoReal	*FindStruct;

	//start a find
	if(!Pattern || !Properties)
		return NULL;

	//allocate memory for the struct
	FindStruct = (FindInfoReal *)malloc(sizeof(FindInfoReal));
	if(!FindStruct)
		return NULL;

	//setup the ID
	FindStruct->FindID = RealFindID;

	//start the find

	//change the current directory
	EnterCriticalSection(&CriticalDirectory);
	GetCurrentDirectory(sizeof(priv_TempCurrentDirectory), priv_TempCurrentDirectory);
	SetCurrentDirectory(priv_CurrentDirectory);

	//grab the first file
	FindStruct->FindHandle = FindFirstFile(Pattern, &FindStruct->FindData);

	//return the directory
	SetCurrentDirectory(priv_TempCurrentDirectory);
	LeaveCriticalSection(&CriticalDirectory);

	//see if the find failed
	if(FindStruct->FindHandle == INVALID_HANDLE_VALUE)
	{
		//find failed, free memory and return false
		free(FindStruct);
		return NULL;
	}

	//completed, convert the data from the struct
	memset(Properties, 0, sizeof(deFileProperties));
	
	//copy the name
	Properties->Filename = FindStruct->FindData.cFileName;
	
	//copy the size
	Properties->Size = FindStruct->FindData.nFileSizeLow;

	//copy the date/time
	Properties->Time = *(s64 *)&FindStruct->FindData.ftLastWriteTime;
	
	//copy any flags, we only care about the directory
	if(FindStruct->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
		Properties->Flags = deFile_Directory;

	//return
	return FindStruct;
}

deBoolean deFSReal::FindNext(void* Handle, deFileProperties *Properties)
{
	FindInfoReal	*FindStruct;

	//if no properties or invalid handle then fail
	if(!Properties || !Handle)
		return deFALSE;

	//see if the handle is valid
	FindStruct = (FindInfoReal *)Handle;
	if(FindStruct->FindID != RealFindID)
		return deFALSE;

	//wipe the properties out
	memset(Properties, 0, sizeof(*Properties));

	//find next
	if(!FindNextFile(FindStruct->FindHandle, &FindStruct->FindData))
		return deFALSE;

	//copy the name
	Properties->Filename = FindStruct->FindData.cFileName;
	
	//copy the size
	Properties->Size = FindStruct->FindData.nFileSizeLow;

	//copy the date/time
	Properties->Time = *(s64 *)&FindStruct->FindData.ftLastWriteTime;
	
	//copy any flags, we only care about the directory
	if(FindStruct->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
		Properties->Flags = deFile_Directory;

	//return
	return deTRUE;
}

deBoolean deFSReal::FindEnd(void* Handle)
{
	FindInfoReal	*FindStruct;

	//if no handle, fail
	if(!Handle)
		return deFALSE;

	//convert the handle
	FindStruct = (FindInfoReal *)Handle;

	//verify the ID
	if(FindStruct->FindID != RealFindID)
		return deFALSE;

	//close the find
	if(FindStruct->FindHandle != INVALID_HANDLE_VALUE)
		FindClose(FindStruct->FindHandle);

	//free the struct
	free(FindStruct);

	//all done
	return deTRUE;
}

#elif linux
void* deFSReal::FindFirst(const char *Pattern, deFileProperties *Properties)
{
 FindInfoReal	*FindStruct;

  //start a find
  if(!Pattern || !Properties)
		return NULL;

	//allocate memory for the struct
	FindStruct = (FindInfoReal *)malloc(sizeof(FindInfoReal));
	if(!FindStruct)
		return NULL;

    //setup the ID
	FindStruct->FindID = RealFindID;
 
   // Setup the Pattern
   assert(strlen(Pattern) > 0);
   FindStruct->Pattern = new char(strlen(Pattern)+1);
   strcpy(FindStruct->Pattern,Pattern);           

	//start the find
  	//change the current directory
  	pthread_mutex_lock(&CriticalDirectory);
	getcwd(priv_TempCurrentDirectory,sizeof(priv_TempCurrentDirectory));
	chdir(priv_CurrentDirectory);

   //grab the first file
   FindStruct->FindDir = opendir("./");
   if(FindStruct->FindDir == NULL)
   {
      delete FindStruct->Pattern;
      free(FindStruct);
      return NULL;
   }
    
	//FindStruct->FindHandle = FindFirstFile(Pattern, &FindStruct->FindData);

	//return the directory
	chdir(priv_TempCurrentDirectory);
	pthread_mutex_unlock(&CriticalDirectory);

   //completed, convert the data from the struct
	memset(Properties, 0, sizeof(deFileProperties));

    if(!FindNext(FindStruct,Properties))
    {
      closedir(FindStruct->FindDir);
      delete FindStruct->Pattern;
      free(FindStruct);
      return NULL;
    }
      
	//return
	return FindStruct;
}

deBoolean deFSReal::FindNext(void* Handle, deFileProperties *Properties)
{
    FindInfoReal	*FindStruct;

	//if no properties or invalid handle then fail
	if(!Properties || !Handle)
		return deFALSE;

	//see if the handle is valid
	FindStruct = (FindInfoReal *)Handle;
	if(FindStruct->FindID != RealFindID)
		return deFALSE;

	//wipe the properties out
	memset(Properties, 0, sizeof(*Properties));

  	//find next
   dirent * Entry;
   while(1)
   {
        Entry = readdir(FindStruct->FindDir);
        if(!Entry)
		    return deFALSE;

        if(fnmatch(FindStruct->Pattern,Entry->d_name,0) == 0)
          break;
   }
	// Set the name pointer
	Properties->Filename = Entry->d_name;

	//change the current directory
   pthread_mutex_lock(&CriticalDirectory);
	getcwd(priv_TempCurrentDirectory,sizeof(priv_TempCurrentDirectory));
	chdir(priv_CurrentDirectory);

    struct stat EntryInfo;
    if(stat(Entry->d_name,&EntryInfo) == -1)
      return deFALSE;

   	//return the directory
	chdir(priv_TempCurrentDirectory);
	pthread_mutex_unlock(&CriticalDirectory);

  
	//copy the size
	Properties->Size = EntryInfo.st_size;

   //copy the date/time
	Properties->Time = EntryInfo.st_mtime;

   if(S_ISDIR(EntryInfo.st_mode))
         Properties->Flags = deFile_Directory;

   //return
	return deTRUE;
}

deBoolean deFSReal::FindEnd(void* Handle)
{
	FindInfoReal	*FindStruct;

	//if no handle, fail
	if(!Handle)
		return deFALSE;

	//convert the handle
	FindStruct = (FindInfoReal *)Handle;

	//verify the ID
	if(FindStruct->FindID != RealFindID)
		return deFALSE;

	//close the find
	if(FindStruct->FindDir)
		closedir(FindStruct->FindDir);

	//free the struct
    delete FindStruct->Pattern;
	free(FindStruct);

   //all done
	return deTRUE;
}
#else
#error File Finding not written for OS
#endif
