Exemple #1
0
MF_API bool MFFileSystem_FindNext(MFFind *pFind, MFFindData *pFindData)
{
	GET_MODULE_DATA(MFFileSystemState);

	if(!(pFind->pMount->volumeInfo.flags & MFMF_DontCacheTOC))
	{
		size_t id = (size_t)pFind->pFilesystemData + 1;

		for(; id < pFind->pMount->numFiles; ++id)
		{
			if(MFString_PatternMatch(pFind->searchPattern, pFind->pMount->pEntries[id].pName))
				break;
		}

		if(id < pFind->pMount->numFiles)
		{
			MFString_Copy(pFindData->pFilename, pFind->pMount->pEntries[id].pName);
			MFString_Copy(pFindData->pSystemPath, (char*)pFind->pMount->pEntries[id].pFilesysData);

			pFindData->info = pFind->pMount->pEntries[id].info;

			pFind->pFilesystemData = (void*)id;
		}
		else
			return false;
	}
	else
		return pModuleData->ppFileSystemList[pFind->pMount->volumeInfo.fileSystem]->callbacks.FindNext(pFind, pFindData);

	return true;
}
Exemple #2
0
void MFFileSystem_UnregisterFileSystem(MFFileSystemHandle filesystemHandle)
{
	MFDebug_Assert((uint32)filesystemHandle < gDefaults.filesys.maxFileSystems, "Invalid filesystem");

	GET_MODULE_DATA(MFFileSystemState);

	MFFileSystem *pFS = pModuleData->ppFileSystemList[filesystemHandle];
	MFDebug_Assert(pFS, "Filesystem not mounted");

	if(pFS->callbacks.UnregisterFS)
		pFS->callbacks.UnregisterFS();

	if(pFS->thread)
	{
		// terminate job thread
		MFJob *pJob = NewJob(pFS);
		PostJob(pFS, pJob);
		while(pJob->status != MFJS_Finished)
		{
			// yield
		}

		MFThread_DestroySemaphore(pFS->semaphore);
		pFS->jobs.Deinit();
		MFHeap_Free(pFS->ppJobQueue);
	}

	pModuleData->gFileSystems.Destroy(pFS);
	pModuleData->ppFileSystemList[filesystemHandle] = NULL;
}
Exemple #3
0
MF_API int MFFileSystem_Dismount(const char *pMountpoint)
{
	GET_MODULE_DATA(MFFileSystemState);

	MFMount *pT = MFFileSystem_FindVolume(pMountpoint);

	if(pT)
	{
		// dismount
		pModuleData->ppFileSystemList[pT->volumeInfo.fileSystem]->callbacks.FSDismount(pT);

		// remove mount
		if(pModuleData->pMountList == pT)
			pModuleData->pMountList = pT->pNext;
		if(pModuleData->pMountListEnd == pT)
			pModuleData->pMountListEnd = pT->pPrev;

		if(pT->pNext)
			pT->pNext->pPrev = pT->pPrev;
		if(pT->pPrev)
			pT->pPrev->pNext = pT->pNext;

		MFHeap_Free(pT);

		return 0;
	}

	// coundnt find mount..
	return -1;
}
Exemple #4
0
MF_API void MFFileSystem_FindClose(MFFind *pFind)
{
	GET_MODULE_DATA(MFFileSystemState);

	if(pFind->pMount->volumeInfo.flags & MFMF_DontCacheTOC)
		pModuleData->ppFileSystemList[pFind->pMount->volumeInfo.fileSystem]->callbacks.FindClose(pFind);

	pModuleData->gFinds.Destroy(pFind);
}
Exemple #5
0
MF_API int MFFile_Close(MFFile* fileHandle)
{
	GET_MODULE_DATA(MFFileSystemState);

	pModuleData->ppFileSystemList[fileHandle->filesystem]->callbacks.Close(fileHandle);
	pModuleData->gOpenFiles.Free(fileHandle);

	return 0;
}
Exemple #6
0
MFMount* MFFileSystem_FindVolume(const char *pVolumeName)
{
	GET_MODULE_DATA(MFFileSystemState);

	for(MFMount *pT = pModuleData->pMountList; pT; pT = pT->pNext)
	{
		if(!MFString_CaseCmp(pT->volumeInfo.pVolumeName, pVolumeName))
			return pT;
	}

	return NULL;
}
Exemple #7
0
// open a file from the mounted filesystem stack
MF_API MFFile* MFFileSystem_Open(const char *pFilename, uint32 openFlags)
{
	MFDebug_Log(5, MFStr("Call: MFFileSystem_Open(\"%s\", 0x%x)", pFilename, openFlags));

	GET_MODULE_DATA(MFFileSystemState);

	MFMount *pMount = pModuleData->pMountList;
	const char *pMountpoint = NULL;

	// search for a mountpoint
	size_t len = MFString_Length(pFilename);
	for(size_t a=0; a<len; a++)
	{
		if(pFilename[a] == ':')
		{
			pMountpoint = MFStrN(pFilename, a);
			pFilename += a+1;
			break;
		}

		if(pFilename[a] == '.')
		{
			// if we have found a dot, this cant be a mountpoint
			// (mountpoints may only be alphanumeric)
			break;
		}
	}

	// search for file through the mount list...
	while(pMount)
	{
		int onlyexclusive = pMount->volumeInfo.flags & MFMF_OnlyAllowExclusiveAccess;

		if((!pMountpoint && !onlyexclusive) || (pMountpoint && !MFString_CaseCmp(pMountpoint, pMount->volumeInfo.pVolumeName)))
		{
			// open the file from a mount
			MFFile *hFile = pModuleData->ppFileSystemList[pMount->volumeInfo.fileSystem]->callbacks.FSOpen(pMount, pFilename, openFlags);

			if(hFile)
				return hFile;
		}

		pMount = pMount->pNext;
	}

	if(!(openFlags & MFOF_TryOpen))
		MFDebug_Warn(4, MFStr("MFFile_Open(\"%s\", 0x%x) - Failed to open file", pFilename, openFlags));

	return NULL;
}
Exemple #8
0
MF_API int MFFileSystem_GetNumVolumes()
{
	GET_MODULE_DATA(MFFileSystemState);

	int numVolumes = 0;

	MFMount *pMount = pModuleData->pMountList;

	while(pMount)
	{
		++numVolumes;
		pMount = pMount->pNext;
	}

	return numVolumes;
}
Exemple #9
0
MF_API void MFFileSystem_GetVolumeInfo(int volumeID, MFVolumeInfo *pVolumeInfo)
{
	GET_MODULE_DATA(MFFileSystemState);

	MFMount *pMount = pModuleData->pMountList;

	while(pMount && volumeID)
	{
		--volumeID;
		pMount = pMount->pNext;
	}

	MFDebug_Assert(pMount, "Invalid volume ID");

	*pVolumeInfo = pMount->volumeInfo;
}
Exemple #10
0
///////////////////////////
// file access functions
MF_API MFFile* MFFile_Open(MFFileSystemHandle fileSystem, MFOpenData *pOpenData)
{
	GET_MODULE_DATA(MFFileSystemState);

	MFFile *pFile = (MFFile*)pModuleData->gOpenFiles.AllocAndZero();
	pFile->filesystem = fileSystem;

	int result = pModuleData->ppFileSystemList[fileSystem]->callbacks.Open(pFile, pOpenData);

	if(result < 0)
	{
		pModuleData->gOpenFiles.Free(pFile);
		return NULL;
	}

	return pFile;
}
Exemple #11
0
MFInitStatus MFFileSystem_InitFileSystems(int moduleId, bool bPerformInitialisation)
{
	GET_MODULE_DATA(MFFileSystemState);

	pModuleData->hNativeFileSystem = ((MFFileSystemGlobalState*)gpEngineInstance->modules[gFileSystemNativeId].pModuleData)->hFileSystemHandle;
	pModuleData->hMemoryFileSystem = ((MFFileSystemGlobalState*)gpEngineInstance->modules[gFileSystemMemoryId].pModuleData)->hFileSystemHandle;
	pModuleData->hCachedFileSystem = ((MFFileSystemGlobalState*)gpEngineInstance->modules[gFileSystemCachedFileId].pModuleData)->hFileSystemHandle;
	pModuleData->hZipFileSystem = ((MFFileSystemGlobalState*)gpEngineInstance->modules[gFileSystemZipFileId].pModuleData)->hFileSystemHandle;
	pModuleData->hHTTPFileSystem = ((MFFileSystemGlobalState*)gpEngineInstance->modules[gFileSystemHTTPId].pModuleData)->hFileSystemHandle;

	// call the filesystem init callback
	MFSystemCallbackFunction pFilesystemInitCallback = MFSystem_GetSystemCallback(MFCB_FileSystemInit);
	if(pFilesystemInitCallback)
		pFilesystemInitCallback();

	return MFIS_Succeeded;
}
Exemple #12
0
MFFileSystemHandle MFFileSystem_RegisterFileSystem(const char *pFilesystemName, MFFileSystemCallbacks *pCallbacks)
{
	MFDebug_Log(5, MFStr("Call: MFFileSystem_RegisterFileSystem(\"%s\")", pFilesystemName));

	GET_MODULE_DATA(MFFileSystemState);

	for(uint32 a=0; a<gDefaults.filesys.maxFileSystems; a++)
	{
		if(pModuleData->ppFileSystemList[a] == NULL)
		{
			MFDebug_Assert(pCallbacks->Open, "No Open function supplied.");
			MFDebug_Assert(pCallbacks->Close, "No Close function supplied.");
			MFDebug_Assert(pCallbacks->Read, "No Read function supplied.");
			MFDebug_Assert(pCallbacks->Write, "No Write function supplied.");
			MFDebug_Assert(pCallbacks->Seek, "No Seek function supplied.");

			MFFileSystem *pFS = pModuleData->gFileSystems.Create();
			MFZeroMemory(pFS, sizeof(MFFileSystem));
			MFString_Copy(pFS->name, pFilesystemName);
			MFCopyMemory(&pFS->callbacks, pCallbacks, sizeof(MFFileSystemCallbacks));
			pModuleData->ppFileSystemList[a] = pFS;

#if defined(USE_JOB_THREAD)
			pFS->ppJobQueue = (MFJob**)MFHeap_Alloc(sizeof(MFJob*)*MAX_JOBS);
			pFS->jobs.Init(MFStr("%s Job List", pFilesystemName), MAX_JOBS+2);
			pFS->readJob = 0;
			pFS->writeJob = 0;
			pFS->numJobs = MAX_JOBS;
			pFS->semaphore = MFThread_CreateSemaphore("Filesystem Semaphore", MAX_JOBS, 0);
			pFS->thread = MFThread_CreateThread(MFStr("%s Thread", pFilesystemName), MKFileJobThread, pFS, MFPriority_AboveNormal);
#endif

			if(pFS->callbacks.RegisterFS)
				pFS->callbacks.RegisterFS();

			return a;
		}
	}

	MFDebug_Assert(false, MFStr("Exceeded maximum of %d Filesystems. Modify 'gDefaults.filesys.maxFileSystems'.", gDefaults.filesys.maxFileSystems));

	return -1;
}
Exemple #13
0
// return a handle to a specific filesystem
MF_API MFFileSystemHandle MFFileSystem_GetInternalFileSystemHandle(MFFileSystemHandles fileSystemHandle)
{
	GET_MODULE_DATA(MFFileSystemState);

	switch(fileSystemHandle)
	{
		case MFFSH_NativeFileSystem:
			MFDebug_Assert(pModuleData->hNativeFileSystem > -1, "Native filesystem is not available...");
			if(pModuleData->hNativeFileSystem < 0)
				MFDebug_Error("Native filesystem is not available...");
			return pModuleData->hNativeFileSystem;
		case MFFSH_MemoryFileSystem:
			MFDebug_Assert(pModuleData->hMemoryFileSystem > -1, "Memory file filesystem is not available...");
			if(pModuleData->hMemoryFileSystem < 0)
				MFDebug_Error("Memory file filesystem is not available...");
			return pModuleData->hMemoryFileSystem;
		case MFFSH_CachedFileSystem:
			MFDebug_Assert(pModuleData->hCachedFileSystem > -1, "Memory file filesystem is not available...");
			if(pModuleData->hCachedFileSystem < 0)
				MFDebug_Error("Cached file filesystem is not available...");
			return pModuleData->hCachedFileSystem;
		case MFFSH_ZipFileSystem:
			MFDebug_Assert(pModuleData->hZipFileSystem > -1, "Zip file filesystem is not available...");
			if(pModuleData->hZipFileSystem < 0)
				MFDebug_Error("Zip file filesystem is not available...");
			return pModuleData->hZipFileSystem;
		case MFFSH_HTTPFileSystem:
			MFDebug_Assert(pModuleData->hHTTPFileSystem > -1, "HTTP file filesystem is not available...");
			if(pModuleData->hHTTPFileSystem < 0)
				MFDebug_Error("HTTP file filesystem is not available...");
			return pModuleData->hHTTPFileSystem;
		case MFFSH_FTPFileSystem:
			MFDebug_Assert(pModuleData->hFTPFileSystem > -1, "FTP file filesystem is not available...");
			if(pModuleData->hFTPFileSystem < 0)
				MFDebug_Error("FTP file filesystem is not available...");
			return pModuleData->hFTPFileSystem;
		default:
			MFDebug_Error(MFStr("Invalid filesystem handle: %d", fileSystemHandle));
			return -1;
	}
}
Exemple #14
0
void MFFileSystem_DeinitModule()
{
	GET_MODULE_DATA(MFFileSystemState);

	if(pModuleData->hDataArchive)
	{
		MFFile_Close(pModuleData->hDataArchive);
	}

	MFFileSystemHTTP_DeinitModule();
	MFFileSystemZipFile_DeinitModule();
	MFFileSystemCachedFile_DeinitModule();
	MFFileSystemMemory_DeinitModule();
	MFFileSystemNative_DeinitModule();

	MFHeap_Free(pModuleData->ppFileSystemList);

	pModuleData->gFileSystems.Deinit();
	pModuleData->gOpenFiles.Deinit();
	pModuleData->gFinds.Deinit();
}
Exemple #15
0
MF_API const char *MFFileSystem_ResolveSystemPath(const char *pFilename, bool bAbsolute)
{
	MFFile *pFile = MFFileSystem_Open(pFilename, MFOF_Read|MFOF_Binary);

	const char *pPath = NULL;
	if(pFile)
	{
		GET_MODULE_DATA(MFFileSystemState);

		// TODO: support other filesystems that forward to the native filesystem (like cache filesystem?)
		if(pFile->filesystem == pModuleData->hNativeFileSystem)
			pPath = MFStr(pFile->fileIdentifier);
		MFFile_Close(pFile);
	}

	// convert to absolute...
	if(bAbsolute)
		pPath = MFFileNative_MakeAbsolute(pPath);

	return pPath;
}
Exemple #16
0
// mount a filesystem
MF_API int MFFileSystem_Mount(MFFileSystemHandle fileSystem, MFMountData *pMountData)
{
	GET_MODULE_DATA(MFFileSystemState);

	MFMount *pMount;
	pMount = (MFMount*)MFHeap_AllocAndZero(sizeof(MFMount) + MFString_Length(pMountData->pMountpoint) + 1);

	pMount->volumeInfo.flags = pMountData->flags;
	pMount->volumeInfo.fileSystem = fileSystem;
	pMount->volumeInfo.priority = pMountData->priority;
	pMount->volumeInfo.pVolumeName = (const char*)&pMount[1];
	MFString_Copy((char*)&pMount[1], pMountData->pMountpoint);

	// call the mount callback
	int result = pModuleData->ppFileSystemList[fileSystem]->callbacks.FSMount(pMount, pMountData);

	if(result < 0)
	{
		MFHeap_Free(pMount);
		return -1;
	}

	return MFFileSystem_AddVolume(pMount);
}
Exemple #17
0
int MFFileSystem_AddVolume(MFMount *pMount)
{
	GET_MODULE_DATA(MFFileSystemState);

	// hook it up..
	if(!pModuleData->pMountList)
	{
		pModuleData->pMountList = pModuleData->pMountListEnd = pMount;
		pMount->pPrev = pMount->pNext = NULL;
	}
	else
	{
		MFMount *pT = pModuleData->pMountList;

		while(pT && pT->volumeInfo.priority < pMount->volumeInfo.priority)
			pT = pT->pNext;

		if(pT)
		{
			if(pT == pModuleData->pMountList)
				pModuleData->pMountList = pMount;

			pMount->pPrev = pT->pPrev;
			pMount->pNext = pT;
			pT->pPrev = pMount;

			if(pMount->pPrev)
				pMount->pPrev->pNext = pMount;
		}
		else
		{
			pMount->pPrev = pModuleData->pMountListEnd;
			pModuleData->pMountListEnd->pNext = pMount;
			pModuleData->pMountListEnd = pMount;
		}
	}

	// build toc
	if(!(pMount->volumeInfo.flags & MFMF_DontCacheTOC))
	{
		MFDebug_Assert(pModuleData->ppFileSystemList[pMount->volumeInfo.fileSystem]->callbacks.FindFirst, "Filesystem must provide a set of find functions to cache the TOC");

		MFFindData findData;
		MFFind *hFind;

		bool flatten = (pMount->volumeInfo.flags & MFMF_FlattenDirectoryStructure) != 0;
		bool recursive = (pMount->volumeInfo.flags & MFMF_Recursive) != 0;

		pMount->volumeInfo.flags |= MFMF_DontCacheTOC;

		const char *pFindPath = MFStr("%s:", pMount->volumeInfo.pVolumeName);

		// this is a crude way to check if the directory exists..
		// TODO: improve this!!
		hFind = MFFileSystem_FindFirst(MFStr("%s*", pFindPath), &findData);

		if(!hFind)
		{
			MFDebug_Warn(1, "FileSystem: Couldnt Mount FileSystem.");
			return -1;
		}

		MFFileSystem_FindClose(hFind);

		// build the TOC
		size_t stringCacheSize = 0;
		pMount->numFiles = MFFileSystem_GetNumEntries(pFindPath, recursive, flatten, &stringCacheSize);

		int sizeOfToc = sizeof(MFTOCEntry)*pMount->numFiles;
		MFTOCEntry *pTOC = (MFTOCEntry*)MFHeap_Alloc(sizeOfToc + stringCacheSize);

		char *pStringCache = (char*)pTOC + sizeOfToc;
		MFFileSystem_BuildToc(pFindPath, pTOC, NULL, pStringCache, recursive, flatten);

		pMount->pEntries = pTOC;

		pMount->volumeInfo.flags &= ~MFMF_DontCacheTOC;
	}

	return 0;
}
Exemple #18
0
MF_API bool MFFile_Delete(MFFileSystemHandle fileSystem, const char *pPath, bool bRecursive)
{
	GET_MODULE_DATA(MFFileSystemState);

	return pModuleData->ppFileSystemList[fileSystem]->callbacks.Delete(pPath, bRecursive);
}
Exemple #19
0
MF_API bool MFFile_CreateDirectory(MFFileSystemHandle fileSystem, const char *pPath)
{
	GET_MODULE_DATA(MFFileSystemState);

	return pModuleData->ppFileSystemList[fileSystem]->callbacks.CreateDir(pPath);
}
Exemple #20
0
// offset management (these are stdio function signature compliant)
MF_API uint64 MFFile_Seek(MFFile* fileHandle, int64 bytes, MFFileSeek relativity)
{
	GET_MODULE_DATA(MFFileSystemState);

	return pModuleData->ppFileSystemList[fileHandle->filesystem]->callbacks.Seek(fileHandle, bytes, relativity);
}
Exemple #21
0
MF_API size_t MFFile_Write(MFFile* fileHandle, const void *pBuffer, size_t bytes, bool async)
{
	GET_MODULE_DATA(MFFileSystemState);

	return pModuleData->ppFileSystemList[fileHandle->filesystem]->callbacks.Write(fileHandle, pBuffer, bytes);
}
Exemple #22
0
MF_API MFFind* MFFileSystem_FindFirst(const char *pSearchPattern, MFFindData *pFindData)
{
	GET_MODULE_DATA(MFFileSystemState);

	const char *pMountpoint = NULL;
	MFFind *pFind = NULL;

	// search for a mountpoint
	const char *pColon = MFString_Chr(pSearchPattern, ':');
	if(pColon)
	{
		pMountpoint = MFStrN(pSearchPattern, pColon - pSearchPattern);
		pSearchPattern = pColon + 1;
	}

	MFDebug_Assert(pMountpoint, "A volume name must be specified in the search pattern.");

	// find the volume
	MFMount *pMount = MFFileSystem_FindVolume(pMountpoint);
	if(!pMount)
	{
		MFDebug_Warn(2, MFStr("MFFileSystem_FindFirst: Volume '%s' in not mounted.", pMountpoint));
		return NULL;
	}

	// search for file through the mount list...
	if(!(pMount->volumeInfo.flags & MFMF_DontCacheTOC))
	{
		if(pMount->numFiles)
		{
			pFind = pModuleData->gFinds.Create();

			pFind->pMount = pMount;
			MFString_Copy(pFind->searchPattern, pSearchPattern);

			size_t file = 0;
			for(; file < pFind->pMount->numFiles; ++file)
			{
				if(MFString_PatternMatch(pSearchPattern, pMount->pEntries[file].pName))
					break;
			}

			if(file == pFind->pMount->numFiles)
			{
				pModuleData->gFinds.Destroy(pFind);
				pFind = NULL;
			}
			else
			{
				pFind->pFilesystemData = (void*)file;

				MFString_Copy(pFindData->pFilename, pMount->pEntries[file].pName);
				MFString_Copy(pFindData->pSystemPath, (char*)pMount->pEntries[file].pFilesysData);

				pFindData->info = pMount->pEntries[file].info;
			}
		}
	}
	else
	{
		pFind = pModuleData->gFinds.Create();

		pFind->pMount = pMount;
		pFind->pFilesystemData = NULL;
		MFString_Copy(pFind->searchPattern, pSearchPattern);

		if(!pModuleData->ppFileSystemList[pMount->volumeInfo.fileSystem]->callbacks.FindFirst(pFind, pSearchPattern, pFindData))
		{
			pModuleData->gFinds.Destroy(pFind);
			pFind = NULL;
		}
	}

	return pFind;
}
Exemple #23
0
MF_API bool MFFile_Stat(MFFileSystemHandle fileSystem, const char *pPath, MFFileInfo *pFileInfo)
{
	GET_MODULE_DATA(MFFileSystemState);

	return pModuleData->ppFileSystemList[fileSystem]->callbacks.Stat(pPath, pFileInfo);
}
Exemple #24
0
void MFFileSystem_RegisterDefaultArchives(void *)
{
	GET_MODULE_DATA(MFFileSystemState);

	MFFile *&hDataArchive = pModuleData->hDataArchive;
	MFFile *&hPatchArchive = pModuleData->hPatchArchive;

	// try and mount the 'standard' archives...
	// TODO: ponder removing this code and forcing the use of a filesystem init callback? :/
	MFOpenDataNative dataArchive;
	dataArchive.cbSize = sizeof(MFOpenDataNative);
	dataArchive.openFlags = MFOF_Read|MFOF_Binary;
	hDataArchive = 0;
	const char **pArc = gArchiveNames;
	while(!hDataArchive && *pArc)
	{
		dataArchive.pFilename =  MFFile_SystemPath(MFStr(*pArc, MFSystem_GetPlatformString(MFSystem_GetCurrentPlatform())));
		hDataArchive = MFFile_Open(pModuleData->hNativeFileSystem, &dataArchive);
		++pArc;
	}

	MFMountDataNative mountData;
	mountData.cbSize = sizeof(MFMountDataNative);
	mountData.priority = MFMP_Normal;

	if(hDataArchive)
	{
		// attempt to cache the zip archive
		MFOpenDataCachedFile cachedOpen;
		cachedOpen.cbSize = sizeof(MFOpenDataCachedFile);
		cachedOpen.openFlags = MFOF_Read | MFOF_Binary | MFOF_Cached_CleanupBaseFile;
		cachedOpen.maxCacheSize = 1*1024*1024; // 1mb cache for zip archives should be heaps!!
		cachedOpen.pBaseFile = hDataArchive;

		MFFile *pCachedFile = MFFile_Open(MFFileSystem_GetInternalFileSystemHandle(MFFSH_CachedFileSystem), &cachedOpen);
		if(pCachedFile)
			hDataArchive = pCachedFile;

		// mount the zip archive.
		MFMountDataZipFile zipMountData;
		zipMountData.cbSize = sizeof(MFMountDataZipFile);
		zipMountData.flags = MFMF_Recursive|MFMF_FlattenDirectoryStructure;
		zipMountData.priority = MFMP_Normal;
		zipMountData.pMountpoint = "data";
		zipMountData.pZipArchive = hDataArchive;
		MFFileSystem_Mount(pModuleData->hZipFileSystem, &zipMountData);
	}

	mountData.flags = MFMF_DontCacheTOC;
	mountData.pMountpoint = "home";
	mountData.pPath = MFFile_HomePath();
	MFFileSystem_Mount(pModuleData->hNativeFileSystem, &mountData);

	// see if we can mount the patch archive..
	hPatchArchive = 0;
	pArc = gPatchArchiveNames;
	while(!hPatchArchive && *pArc)
	{
		dataArchive.pFilename =  MFFile_SystemPath(MFStr(*pArc, MFSystem_GetPlatformString(MFSystem_GetCurrentPlatform())));
		hDataArchive = MFFile_Open(pModuleData->hNativeFileSystem, &dataArchive);
		++pArc;
	}

	if(hPatchArchive)
	{
		// attempt to cache the zip archive
		MFOpenDataCachedFile cachedOpen;
		cachedOpen.cbSize = sizeof(MFOpenDataCachedFile);
		cachedOpen.openFlags = MFOF_Read | MFOF_Binary | MFOF_Cached_CleanupBaseFile;
		cachedOpen.maxCacheSize = 1*1024*1024; // 1mb cache for zip archives should be heaps!!
		cachedOpen.pBaseFile = hPatchArchive;

		MFFile *pCachedFile = MFFile_Open(MFFileSystem_GetInternalFileSystemHandle(MFFSH_CachedFileSystem), &cachedOpen);
		if(pCachedFile)
			hPatchArchive = pCachedFile;

		// mount the zip archive.
		MFMountDataZipFile zipMountData;
		zipMountData.cbSize = sizeof(MFMountDataZipFile);
		zipMountData.flags = MFMF_Recursive|MFMF_FlattenDirectoryStructure;
		zipMountData.priority = MFMP_VeryHigh;
		zipMountData.pMountpoint = "patch";
		zipMountData.pZipArchive = hPatchArchive;
		MFFileSystem_Mount(pModuleData->hZipFileSystem, &zipMountData);
	}

	if(pModuleData->hHTTPFileSystem != -1)
	{
		// register the network filesystems
		MFMountDataHTTP mountDataHTTP;
		mountDataHTTP.cbSize = sizeof(MFMountDataHTTP);
		mountDataHTTP.pMountpoint = "http";
		mountDataHTTP.priority = MFMP_Normal + 1;
		mountDataHTTP.flags = MFMF_OnlyAllowExclusiveAccess;
		MFFileSystem_Mount(pModuleData->hHTTPFileSystem, &mountDataHTTP);
	}
}