/****************************************************************************************/

/*  FSBeos.cpp                                                                          */

/*                                                                                      */

/*  Author:  Christopher Plymire                                                        */

/*  Description:                                                                        */

/*                                                                                      */

/*  The contents of this file are subject to the Jet3D Public License                   */

/*  Version 1.02 (the "License"); you may not use this file except in                   */

/*  compliance with the License. You may obtain a copy of the License at                */

/*  http://www.jet3d.com                                                                */

/*                                                                                      */

/*  Software distributed under the License is distributed on an "AS IS"                 */

/*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */

/*  the License for the specific language governing rights and limitations              */

/*  under the License.                                                                  */

/*                                                                                      */

/*  The Original Code is Jet3D, released December 12, 1999.                             */

/*  Copyright (C) 1996-1999 Eclipse Entertainment, L.L.C. All Rights Reserved           */

/*                                                                                      */

/****************************************************************************************/



#include <StorageKit.h>

#include <Statable.h>

#include <dirent.h>

#include <sys/stat.h> // stat



#include <iostream.h>

#include <time.h>



#include	<stdio.h>

#include	<stdlib.h>

#include	<string.h>

#include	<assert.h>



#include	"BaseType.h"

#include	"Ram.h"



#include	"VFile.h"

#include	"VFile._h"



#include	"FSBeos.h"



// CJP - Update in V2.0 -- File handle leak bug fixed. (BEntry wasn't being "unset")



typedef struct BeOSFinder

{

//	BQuery* pQuery;

	DIR* 	pDir;

		

//	jeBoolean FirstStillCached;

//	BEntry* pFile;

	dirent* pFile;

	

	char Criteria[256]; // This is the string we filter with.  We currently only support *.whatever and whatever.*.

	//  Whatever*Whatever will not work yet..

	

	char* FullPath;

}BeOSFinder;



typedef struct BeOSFile

{

	BFile* pFile; // Will be null if(IsDirectory)

	BDirectory* pDirectory; // Will be null if(!IsDirectory)

	BEntry* pEntry; // Will never be NULL

	

	char* FullPath;

	const char*Name;

	

	jeBoolean IsDirectory;

	

	jeBoolean		CanSetHints; // new in 2.0

	unsigned int	OpenFlags; // new in 2.0

	jeVFile *		HintsFile; // new in 2.0

	off_t			TrueFileBase; // new in 2.0

}BeOSFile;



static	jeBoolean	BuildFileName(

	const BeOSFile *File,

	const char *	Name,

	char *			Buff,

	char **			NamePtr,

	int 			MaxLen)

{

	int		DirLength;

	int		NameLength;



	if ( ! Name )

		return JE_FALSE;



	if	(File)

	{

		if	(File->IsDirectory == JE_FALSE)

			return JE_FALSE;



		assert(File->FullPath);

		DirLength = strlen(File->FullPath);



		if	(DirLength > MaxLen)

			return JE_FALSE;



		memcpy(Buff, File->FullPath, DirLength);

	}

	else

	{

		DirLength = 0;

	}



	NameLength = strlen(Name);

	if	(DirLength + NameLength + 2 > MaxLen || ! Buff )

		return JE_FALSE;



	if	(DirLength != 0)

	{

		Buff[DirLength] = '/';

		memcpy(Buff + DirLength + 1, Name, NameLength + 1);

		if	(NamePtr)

			*NamePtr = Buff + DirLength + 1;

	}

	else

	{

		memcpy(Buff, Name, NameLength + 1);

		if	(NamePtr)

			*NamePtr = Buff;



		// Special case: no directory, no file name.  We meant something like ".\"

		if	(!*Buff)

		{

			strcpy (Buff, "./");

		}

	}



	return JE_TRUE;

}



static	void *	JETCC FSBeOS_Open(

	jeVFile *		FS,

	void *			Handle,

	const char *	Name,

	void *			Context,

	unsigned int 	OpenModeFlags)

{

	BeOSFile *	BeOSFS;

	BeOSFile *	NewFile;

	char		Buff[B_PATH_NAME_LENGTH];

	int			Length;

	char *		NamePtr;



	BeOSFS = (BeOSFile *)Handle;



	if	(BeOSFS && BeOSFS->IsDirectory != JE_TRUE)

		return NULL;



	NewFile = (BeOSFile *)jeRam_Allocate(sizeof(BeOSFile));

	if	(!NewFile)

		return NewFile;



	memset(NewFile, 0, sizeof(BeOSFile));



	if	(BuildFileName(BeOSFS, Name, Buff, &NamePtr, sizeof(Buff)) == JE_FALSE)

		goto fail;



	Length = strlen(Buff);

	NewFile->FullPath = (char *)jeRam_Allocate(Length + 1);

	if	(!NewFile->FullPath)

		goto fail;



	NewFile->Name = NewFile->FullPath + (NamePtr - &Buff[0]);



	memcpy(NewFile->FullPath, Buff, Length + 1);



	if	(OpenModeFlags & JE_VFILE_OPEN_DIRECTORY)

	{

		if(OpenModeFlags & JE_VFILE_OPEN_CREATE)

			create_directory(Buff, 0777);

		

		// Read is 4

		// Write is 2

		// Execute is 1

		

		NewFile->pEntry = new BEntry(Buff);

		if(!NewFile->pEntry->Exists())

		{

		delete NewFile->pEntry;

			goto fail;

		}

		

		NewFile->pDirectory = new BDirectory;

		if(!NewFile->pDirectory)

		{

			delete NewFile->pEntry;

				goto fail;

		}		



		if(NewFile->pDirectory->SetTo(Buff) != B_OK)

		{

		delete NewFile->pEntry;

		delete NewFile->pDirectory;

		goto fail;

		}

		

		NewFile->IsDirectory = JE_TRUE;

		NewFile->pFile = NULL;	

	}

	else

	{



	uint32 OpenMode = 0;



		switch	(OpenModeFlags & (JE_VFILE_OPEN_READONLY |

								  JE_VFILE_OPEN_UPDATE	 |

								  JE_VFILE_OPEN_CREATE))

		{

		case	JE_VFILE_OPEN_READONLY:

			OpenMode = B_READ_ONLY;//OpenMode |= JE_VFILE_OPEN_DIRECTORY;

			

			//ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;

			break;



		case	JE_VFILE_OPEN_CREATE:

			// Fall through

			OpenMode |= B_CREATE_FILE;

								

		case	JE_VFILE_OPEN_UPDATE:

			OpenMode |= B_READ_WRITE; //Access = GENERIC_READ | GENERIC_WRITE;

//			ShareMode = FILE_SHARE_READ;

			break;



		default:

			assert(!"Illegal open mode flags");

			break;

		}



//		NewFile->FileHandle = CreateFile(NewFile->FullPath,

//										 Access,

//										 ShareMode,

//										 NULL,

//										 CreationMode,

//										 0,

//										 NULL);

//		if	(NewFile->FileHandle == INVALID_HANDLE_VALUE)

//			{

//				LastError = GetLastError();

//				goto fail;

//			}*/	

	NewFile->pEntry = new BEntry(NewFile->FullPath);

	if(NewFile->pEntry->Exists())

	{

	NewFile->pFile = new BFile;

	status_t openResult = NewFile->pFile->SetTo(NewFile->FullPath,OpenMode);



	if(openResult != B_NO_ERROR)

	{

		switch(openResult) // Added to aid in debugging

		{

			case B_BAD_VALUE:

				printf("File error : Bad value\n");

				break;

		

			case B_ENTRY_NOT_FOUND:

				printf("File error : Entry not found");

				break;

		

			case B_FILE_EXISTS:

				printf("File error : File exists");

				break;

			

			case B_PERMISSION_DENIED:

				printf("File error : Permission denied\n");

				break;

				

			case B_NO_MEMORY:

				printf("File error : No Memory");

				break;

		}

		goto fail;

	}

	}

	else

	{

	delete NewFile->pEntry;

	goto fail;

	}

		





		/*

			Now we have to go looking in the file to see if it has hint data

			that we need to encapsulate.

		*/

		if	( (OpenModeFlags & (JE_VFILE_OPEN_READONLY | JE_VFILE_OPEN_UPDATE)) &&

			 !(OpenModeFlags & (JE_VFILE_OPEN_RAW)))

		{

			ssize_t					BytesRead;

			jeVFile_HintsFileHeader	HintsHeader;



			BytesRead = NewFile->pFile->Read(&HintsHeader,sizeof(HintsHeader));			

//			ReadFile(NewFile->FileHandle, &HintsHeader, sizeof(HintsHeader), &BytesRead, NULL);

			if	(BytesRead == sizeof(HintsHeader) &&

				 HintsHeader.Signature == JE_VFILE_HINTSFILEHEADER_SIGNATURE)

			{

				/*

					Allocate the hint data, read the data from disk, and set the true file

					base to the resulting file offset.  This will allow us to adjust file

					offsets that the client gets from the other APIs to ignore the hint

					data.

				*/

				jeVFile_MemoryContext	MemoryContext;



				MemoryContext.Data = NULL;

				MemoryContext.DataLength = 0;

				NewFile->HintsFile = jeVFile_OpenNewSystem(NULL,

														   JE_VFILE_TYPE_MEMORY,

														   NULL,

														   &MemoryContext,

														   JE_VFILE_OPEN_CREATE);

				if	(!NewFile->HintsFile)

					goto fail;



				if	(jeVFile_Seek(NewFile->HintsFile, HintsHeader.HintDataLength, JE_VFILE_SEEKSET) == JE_FALSE)

					goto fail;



				jeVFile_UpdateContext(NewFile->HintsFile, &MemoryContext, sizeof(MemoryContext));

				BytesRead = NewFile->pFile->Read(MemoryContext.Data, HintsHeader.HintDataLength); //ReadFile(NewFile->FileHandle, MemoryContext.Data, HintsHeader.HintDataLength, &BytesRead, NULL);

				if	(BytesRead != HintsHeader.HintDataLength)

					goto fail;



				jeVFile_Seek(NewFile->HintsFile, 0, JE_VFILE_SEEKSET);

				NewFile->TrueFileBase = NewFile->pFile->Position(); //SetFilePointer(NewFile->FileHandle, 0, NULL, FILE_CURRENT);

			}

			else

			{

				if( NewFile->pFile->Seek(0, SEEK_SET) == B_ERROR) //if	(SetFilePointer(NewFile->FileHandle, 0, NULL, FILE_BEGIN) == (DWORD)-1)

					goto fail;

				NewFile->CanSetHints = JE_TRUE;

			}

		}

		else

		{

			NewFile->CanSetHints = JE_TRUE;

		}

	}



//	NewFile->Signature = DOSFILE_SIGNATURE;

	NewFile->OpenFlags = OpenModeFlags;



	return (void *)NewFile;



fail:

	if	(NewFile->HintsFile)

		jeVFile_Close(NewFile->HintsFile);

	if	(NewFile->FullPath)

		jeRam_Free(NewFile->FullPath);

	jeRam_Free(NewFile);

	return NULL;

}



static	jeBoolean	JETCC FSBeOS_Write(void *Handle, const void *Buff, int Count)

{

	BeOSFile*	File;

	status_t		BytesWritten;



	assert(Buff);

	assert(Count != 0);



	File = (BeOSFile *)Handle;



//	CHECK_HANDLE(File);



	if	(File->IsDirectory == JE_TRUE)

		return JE_FALSE;

		

	BytesWritten = File->pFile->Write((void *)Buff,Count); //WriteFile(File->FileHandle, Buff, Count, &BytesWritten, NULL) == FALSE)



	if	((int)BytesWritten != Count)

		return JE_FALSE;



	return JE_TRUE;

}



static	void *	JETCC FSBeOS_OpenNewSystem(

	jeVFile *			FS,

	const char *	Name,

	void *			Context,

	unsigned int 	OpenModeFlags)

{

	return FSBeOS_Open(FS, NULL, Name, Context, OpenModeFlags);

}





static	jeBoolean	JETCC FSBeOS_Tell(const void *Handle, long *Position)

{

	const BeOSFile *	File;

	

	File = (const BeOSFile *)Handle;



//	CHECK_HANDLE(File);



	if	(File->IsDirectory == JE_TRUE)

		return JE_FALSE;



	assert(File->pFile != NULL);



	status_t CurPos = File->pFile->Position();

	*Position = CurPos;

	

	*Position -= File->TrueFileBase; 

	

	return JE_TRUE;

}



static	jeBoolean	JETCC FSBeOS_FileExists(jeVFile *FS, void *Handle, const char *Name)

{

	BeOSFile *	File;

	char		Buff[B_PATH_NAME_LENGTH];

	jeBoolean 		found = JE_TRUE;

	

	File = (BeOSFile *)Handle;



	if	(File && File->IsDirectory == JE_FALSE)

		return JE_FALSE;



	if	(BuildFileName(File, Name, Buff, NULL, sizeof(Buff)) == JE_FALSE)

		return JE_FALSE;

	

	BEntry* testEntry = new BEntry(Buff);

	if(!testEntry->Exists())

		found = JE_FALSE;

	

	testEntry->Unset();

	delete testEntry;

	

	return found;

}



static	jeBoolean	JETCC FSBeOS_Size(const void *Handle, long *Size)

{

	const BeOSFile*	File;



	File = (const BeOSFile *)Handle;



//	CHECK_HANDLE(File);



	if	(File->IsDirectory == JE_TRUE)

		return JE_FALSE;



	assert(File->pFile != NULL);



	off_t fileSize;

	if( File->pFile->GetSize(&fileSize) != B_NO_ERROR)

		return JE_FALSE;

	

	*Size = fileSize;

	

	*Size -= File->TrueFileBase; 

	

	return JE_TRUE;	

}



static	jeBoolean	JETCC FSBeOS_SetSize(void *Handle, long size)

{

	BeOSFile*	File;



	File = (BeOSFile *)Handle;



//	CHECK_HANDLE(File);



	if	(File->IsDirectory == JE_FALSE)

	{

		assert(File->pFile != NULL);

		

		if(File->pFile->SetSize(size) != B_NO_ERROR)

			return JE_FALSE;

	

		return JE_TRUE;	

	}



	return JE_FALSE;

}



static	jeBoolean	JETCC FSBeOS_Disperse(

	jeVFile *		FS,

	void *		Handle,

	const char *Directory)

{

	return JE_FALSE;

}



static	jeBoolean	JETCC FSBeOS_RenameFile(jeVFile *FS, void *Handle, const char *Name, const char *NewName)

{

	BeOSFile *	File;

	char		Old[B_PATH_NAME_LENGTH];

	char		New[B_PATH_NAME_LENGTH];



	File = (BeOSFile *)Handle;



	if	(File && File->IsDirectory == JE_FALSE)

		return JE_FALSE;



	if	(BuildFileName(File, Name, Old, NULL, sizeof(Old)) == JE_FALSE)

		return JE_FALSE;



	if	(BuildFileName(File, NewName, New, NULL, sizeof(New)) == JE_FALSE)

		return JE_FALSE;



	BEntry* pEntry = new BEntry(Old);

	if(!pEntry->Exists())

	{

		delete pEntry;

		return JE_FALSE;

	}

	

	if( pEntry->Rename(New) == B_NO_ERROR)

	{

		delete pEntry;

		return JE_TRUE;

	}

//	if	(MoveFile(Old, New) == FALSE)

//		return JE_FALSE;

	delete pEntry;

	return JE_TRUE;

}



static	jeBoolean	JETCC FSBeOS_DeleteFile(jeVFile *FS, void *Handle, const char *Name)

{

	BeOSFile*	File;

	char		Buff[B_PATH_NAME_LENGTH];



	File = (BeOSFile *)Handle;



	if	(File && File->IsDirectory == JE_FALSE) // we only delete from directories..

		return JE_FALSE;



	if	(BuildFileName(File, Name, Buff, NULL, sizeof(Buff)) == JE_FALSE)

		return JE_FALSE;



	BEntry* pEntry = new BEntry(Buff);

	if(!pEntry->Exists())

	{

	delete pEntry;

	return JE_FALSE;

	}

	

	pEntry->Remove(); // we need to make sure no other jeVFile's are referencing this.... but no way to do that right now

	delete pEntry;

	

	return JE_TRUE;

}



static	jeBoolean	JETCC FSBeOS_EOF(const void *Handle)

{

	const BeOSFile *File;

	status_t		CurPos;

	off_t			fileSize = 0;

	

	File = (BeOSFile *)Handle;



//	CHECK_HANDLE(File);



	if	(File->IsDirectory == JE_TRUE)

		return JE_FALSE;



	assert(File->pFile != NULL);



	CurPos = File->pFile->Position();

	File->pFile->GetSize(&fileSize);

	

	if(CurPos == fileSize)

	return JE_TRUE;

	

//	if	(CurPos == GetFileSize(File->FileHandle, NULL))

//		return JE_TRUE;



	return JE_FALSE;

}



static	jeBoolean	JETCC FSBeOS_Seek(void *Handle, int Where, jeVFile_Whence Whence)

{

	int32	RTLWhence;

	BeOSFile *	File;



	File = (BeOSFile *)Handle;



//	CHECK_HANDLE(File);



	if	(File->IsDirectory == JE_TRUE)

		return JE_FALSE;



	switch	(Whence)

	{

	case	JE_VFILE_SEEKCUR:

		RTLWhence = SEEK_CUR;

		break;



	case	JE_VFILE_SEEKEND:

		RTLWhence = SEEK_END;

		break;



	case	JE_VFILE_SEEKSET:

		RTLWhence = SEEK_SET;

		Where += File->TrueFileBase;

		break;

	default:

		assert(!"Unknown seek kind");

	}



	if(	File->pFile->Seek(Where,RTLWhence) == B_ERROR)

		return JE_FALSE;

	

	return JE_TRUE;

}



static	jeBoolean	JETCC FSBeOS_Close(void *Handle)

{

	BeOSFile*	File;

	

	File = (BeOSFile *)Handle;

	

//	CHECK_HANDLE(File);



	delete File->pEntry;

	File->pEntry = NULL;

	

	if	(File->IsDirectory == JE_FALSE)

	{

		assert(File->pFile != NULL);



		File->pFile->Unset();

		delete File->pFile;

	}

	else

	{

		File->pDirectory->Unset();

		delete File->pDirectory;

	}

		

	assert(File->FullPath);

//	File->Signature = 0;

	jeRam_Free(File->FullPath);

	jeRam_Free(File);

	

	// Need to add hint file support..

	return JE_TRUE;

}



static	jeBoolean	JETCC FSBeOS_Read(void *Handle, void *Buff, uint32 Count)

{

	BeOSFile*	File;

	status_t	BytesRead;



	assert(Buff);

	assert(Count != 0);



	File = (BeOSFile *)Handle;



//	CHECK_HANDLE(File);



	if	(File->IsDirectory == JE_TRUE)

		return JE_FALSE;



	BytesRead = File->pFile->Read(Buff,Count); //(File->FileHandle, Buff, MaxLen - 1, &BytesRead, NULL);



//	if	(ReadFile(File->FileHandle, Buff, Count, &BytesRead, NULL) == FALSE)

//		return JE_FALSE;



	if	(BytesRead == 0)

	{

		printf("Error reading from file!\n");

		return JE_FALSE;

	}



	return JE_TRUE;

}



static	jeBoolean	JETCC FSBeOS_UpdateContext(

	jeVFile *		FS,

	void *			Handle,

	void *			Context,

	int 			ContextSize)

{

	return JE_FALSE;

}



static	jeBoolean	JETCC FSBeOS_GetS(void *Handle, void *Buff, int MaxLen)

{

	BeOSFile *	File;

	ssize_t		BytesRead = 0;



	off_t seekback = 0;

	char *		p = NULL;

	char *		End = NULL; 



	assert(Buff);

	assert(MaxLen != 0);



	File = (BeOSFile *)Handle;



	if	(File->IsDirectory == JE_TRUE) // dont want to read a directory...

		return JE_FALSE;

		

	assert(File->pFile != NULL);

	size_t Maxlength = MaxLen;

	

	off_t oldPos = File->pFile->Position();

	BytesRead = File->pFile->Read(Buff,Maxlength);//Read(Buff,MaxLen); //(File->FileHandle, Buff, MaxLen - 1, &BytesRead, NULL);



	if	(BytesRead == 0)

	{

		return JE_FALSE;

	}



//	if( BytesRead > 0 && BytesRead < Maxlength)

//		Buff[BytesRead] = '\0';

		

	End = (char *)Buff;

	End += (int)BytesRead;

	p = (char *)Buff;

	while	(p < End)

	{

		/*

		  This code will terminate a line on one of three conditions:

			\r	Character changed to \n, next char set to 0

			\n	Next char set to 0

			\r\n	First \r changed to \n.  \n changed to 0.

		*/

		if	(*p == '\r')

		{

			int32 Skip = 0;

			

			*p = '\n';		// set end of line

			p++;			// and skip to next char

			// If the next char is a newline, then skip it too  (\r\n case)

			if (*p == '\n')

			{

				Skip = 1;

			}

			*p = '\0';

			// Set the file pointer back a bit since we probably overran

			

			// this is really pathetic this compiler wont types by negative one or negate the result

			

			seekback = -((int)((BytesRead - ((p + Skip) - (char *)Buff))));

			//seekback = -200;

//			off_t seekneg = seekback * -1; //seekback - seekback * 2;

//			printf("SEEKNEG : %i\n", seekneg);

			 

			off_t newPos = File->pFile->Seek(seekback,SEEK_CUR);

			

			

			oldPos = File->pFile->Position();



			return JE_TRUE;

		}

		else if	(*p == '\n')

		{

			// Set the file pointer back a bit since we probably overran

			p++;

//			SetFilePointer(File->FileHandle, -(int)(BytesRead - (p - (char *)Buff)), NULL, FILE_CURRENT); 

//			*p = '\0';

//			assert(p - (char *)Buff <= MaxLen);

//			return JE_TRUE;



			seekback = (-(int)(BytesRead - (p - (char *)Buff)));

			File->pFile->Seek(-(int)(BytesRead - (p - (char *)Buff)),SEEK_CUR); 

			*p = '\0';

			assert(p - (char *)Buff <= MaxLen);

			return JE_TRUE;

		}

		p++;

	}



	return JE_FALSE;

}



static	jeBoolean	JETCC FSBeOS_SetAttributes(void *Handle, jeVFile_Attributes Attributes)

{

	BeOSFile *	File;



	File = (BeOSFile *)Handle;



	if	(File->IsDirectory == JE_TRUE)

		return JE_FALSE;

		

	assert(File->pFile != NULL);



/*	if	(Attributes & GE_VFILE_ATTRIB_READONLY)

		Win32Attributes = FILE_ATTRIBUTE_READONLY;

	else

		Win32Attributes = FILE_ATTRIBUTE_NORMAL;

*/

	mode_t currentPerms;

	

	File->pFile->GetPermissions(&currentPerms);

	

	return JE_TRUE;

}





static	void *	JETCC FSBeOS_FinderCreate(

	jeVFile *			FS,

	void *			Handle,

	const char *	FileSpec)

{

	BeOSFinder *		Finder;

	BeOSFile   *		File;

	char *			NamePtr;

	char			Buff[B_PATH_NAME_LENGTH];



	assert(FileSpec != NULL);



	File = (BeOSFile *)Handle;



//	CHECK_HANDLE(File);



	Finder = (BeOSFinder *)jeRam_Allocate(sizeof(BeOSFinder));

	if	(!Finder)

		return NULL;



	memset(Finder, 0, sizeof(BeOSFinder));



	if	(BuildFileName(File, FileSpec, Buff, &NamePtr, sizeof(Buff)) == JE_FALSE)

	{

		jeRam_Free(Finder);

		return NULL;

	}



	Finder->pDir = opendir(File->FullPath);

	if(Finder->pDir == NULL)

	{

		printf("Unable to open finder.\n");

		return NULL;

	}

	

	// Now for the criteria string we merely strip the wildcards (*) and then use strstr to search for the string in the file name

	char* destPtr = &Finder->Criteria[0];

	char* srcPtr = (char *)&FileSpec[0];

	

	while(srcPtr && *srcPtr != '\0')

	{

		if(*srcPtr != '*')

		{

			*destPtr = *srcPtr;

			destPtr++;

			srcPtr++;

		}

		else // if its the wildcard, don't copy and advance the source string.

		srcPtr++;

	}

		

	return (void *)Finder;

}



static	jeBoolean	JETCC FSBeOS_FinderGetNextFile(void *Handle)

{

	BeOSFinder*	Finder;



	Finder = (BeOSFinder *)Handle;

	

	Finder->pFile = readdir(Finder->pDir);

	

	while(Finder->pFile)

	{

		if(strstr(Finder->pFile->d_name, Finder->Criteria) != NULL)

			break;

			

		Finder->pFile = readdir(Finder->pDir);

	}

	

	if(!Finder->pFile)

		return JE_FALSE;

		

	return JE_TRUE;

}



static	jeBoolean	JETCC FSBeOS_FinderGetProperties(void *Handle, jeVFile_Properties *Props)

{



	BeOSFinder *			Finder;



	struct stat fileStat;

	jeVFile_Attributes	Attribs;

	int					Length;



	assert(Props);



	Finder = (BeOSFinder *)Handle;



//	CHECK_FINDER(Finder);



	if	(Finder->pFile == NULL)//INVALID_HANDLE_VALUE)

		return JE_FALSE;



	strcpy(Props->Name, Finder->pFile->d_name);

	

#if 0

	Finder->pFile->GetStat(&fileStat);

	

	

	Attribs = 0;

	if	(Finder->pFile->IsDirectory())//FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)

		Attribs |= JE_VFILE_ATTRIB_DIRECTORY;

//	if	(Finder->FindData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)

//		Attribs |= GE_VFILE_ATTRIB_READONLY;



//	Props->Time.Time1 = stat.st_ctime;//Finder->FindData.ftLastWriteTime.dwLowDateTime;

//	Props->Time.Time2 = Finder->FindData.ftLastWriteTime.dwHighDateTime;



	Props->AttributeFlags = Attribs;

	Props->Size = fileStat.st_size;//Finder->FindData.nFileSizeLow;



//	Length = strlen(Finder->FindData.cFileName);

//	if	(Length > sizeof(Props->Name) - 1)

//		return JE_FALSE;

	Finder->pFile->GetName(Props->Name);////memcpy(Props->Name, Finder->pFile->GetNameFinder->FindData.cFileName, Length + 1);

#endif



	return JE_TRUE;

}



static	void JETCC FSBeOS_FinderDestroy(void *Handle)

{

	BeOSFinder*	Finder;



	Finder = (BeOSFinder *)Handle;



//	CHECK_FINDER(Finder);



//	if	(Finder->FindHandle != INVALID_HANDLE_VALUE)

//		FindClose(Finder->FindHandle);



	if( Finder->pDir)

	{

		closedir(Finder->pDir);

		Finder->pDir = NULL;

	}

	

//	Finder->Signature = 0;

	jeRam_Free(Finder);

}



// Extinct in 2.0

#if 0

static	jeBoolean	JETCC FSBeOS_SetHints(void *Handle, const jeVFile_Hints *Hints)

{

	return JE_FALSE;

}

#endif



// ** BeOS Alarm ** 

// I need to fix this... 

// Right now im not sure what the two time fields should be.. 

// Looks to be designed for win32..



static	jeBoolean	JETCC FSBeOS_SetTime(void *Handle, const jeVFile_Time *Time)

{

	BeOSFile*	File;



	File = (BeOSFile *)Handle;



//	CHECK_HANDLE(File);

	if(File->IsDirectory)

		return JE_FALSE;

		

	assert(File->pFile != NULL);

	

	time_t CreationTime;

 	

// 	File->pFile->SetModificationTime(CreationTime);



		//Win32Time.dwLowDateTime  = Time->Time1;

	//Win32Time.dwHighDateTime = Time->Time2;

	//if	(SetFileTime(File->FileHandle, &Win32Time, &Win32Time, &Win32Time) == FALSE)

	//	return JE_FALSE;



	return JE_TRUE;

}



//BeOS ALARM!!

//Didnt even feel like implementing this yet...

static	jeBoolean	JETCC FSBeOS_GetProperties(const void *Handle, jeVFile_Properties *Properties)

{

/*

	const BeOSFile *			File;

	jeVFile_Attributes			Attribs;

//	BY_HANDLE_FILE_INFORMATION	Info;

	int							Length;



	assert(Properties);



	File = Handle;



//	CHECK_HANDLE(File);



	if	(File->IsDirectory == JE_TRUE)

	{

		memset(Properties, 0, sizeof(*Properties));

		Properties->AttributeFlags = FILE_ATTRIBUTE_DIRECTORY;

#pragma message ("FSDos_GetProperties: Time support is not there for directories")

	}

	else

	{

		assert(File->FileHandle != INVALID_HANDLE_VALUE);

	

		if	(GetFileInformationByHandle(File->FileHandle, &Info) == FALSE)

			return JE_FALSE;

	

		Attribs = 0;

		if	(Info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)

			Attribs |= GE_VFILE_ATTRIB_DIRECTORY;

		if	(Info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)

			Attribs |= GE_VFILE_ATTRIB_READONLY;

	

		Properties->Time.Time1 = Info.ftLastWriteTime.dwLowDateTime;

		Properties->Time.Time2 = Info.ftLastWriteTime.dwHighDateTime;

	

		Properties->AttributeFlags 		 = Attribs;

		Properties->Size		  		 = Info.nFileSizeLow;

		Properties->Hints.HintData		 = NULL;

		Properties->Hints.HintDataLength = 0;

	}



	Length = strlen(File->Name) + 1;

	if	(Length > sizeof(Properties->Name))

		return JE_FALSE;

	memcpy(Properties->Name, File->Name, Length);

*/

	return JE_TRUE;

}



static	jeBoolean	JETCC FSBeOS_BytesAvailable(void *Handle, long *Count)

{

	BeOSFile *	File;

	off_t EndPos, CurrentPos;

	File = (BeOSFile *)Handle;



//	CHECK_HANDLE(File);



	assert(Count);



	if	(File->IsDirectory == JE_TRUE)

		return JE_FALSE;



	assert(File->pFile != NULL);





	if(File->pFile->GetSize(&EndPos) != B_OK)

		return JE_FALSE;

		

	CurrentPos = File->pFile->Position();

	

	*Count = EndPos - CurrentPos;	



	return JE_TRUE;

}



static	jeVFile *	JETCC FSBeOS_GetHintsFile(void *Handle)

{

	BeOSFile *	File;



	File = (BeOSFile *)Handle;



//	CHECK_HANDLE(File);



	if	(File->OpenFlags & JE_VFILE_OPEN_RAW)

		return NULL;



	if	(!File->HintsFile)

	{

		jeVFile_MemoryContext	Context;



		// Can't create hints on a readonly file

		if	(File->OpenFlags & JE_VFILE_OPEN_READONLY)

			return NULL;



		Context.Data = NULL;

		Context.DataLength = 0;

		File->HintsFile = jeVFile_OpenNewSystem(NULL,

												JE_VFILE_TYPE_MEMORY,

												NULL,

												&Context,

												JE_VFILE_OPEN_CREATE);

	}



	return File->HintsFile;

}





static	jeVFile_SystemAPIs	FSBeOS_APIs =

{

	FSBeOS_FinderCreate, // structured

	FSBeOS_FinderGetNextFile, //structured

	FSBeOS_FinderGetProperties, //structured

	FSBeOS_FinderDestroy, //structured



	FSBeOS_OpenNewSystem, // done

	FSBeOS_UpdateContext, // done 

	FSBeOS_Open, // done

	FSBeOS_DeleteFile, //done

	FSBeOS_RenameFile, //done

	FSBeOS_FileExists, // done

	FSBeOS_Disperse, // done

	FSBeOS_Close, // done



	FSBeOS_GetS, // done

	FSBeOS_BytesAvailable, // done (new in 2.0)

	FSBeOS_Read, // done

	FSBeOS_Write, // done

	FSBeOS_Seek, // done 

	FSBeOS_EOF, // done 

	FSBeOS_Tell, // done

	FSBeOS_Size, // done



	FSBeOS_GetProperties,



	FSBeOS_SetSize, // done

	FSBeOS_SetAttributes,

	FSBeOS_SetTime,

	

	FSBeOS_GetHintsFile,

};



const jeVFile_SystemAPIs *JETCC FSBeOS_GetAPIs(void)

{

	return &FSBeOS_APIs;

}



