static int MFFileSystem_GetNumEntries(const char *pFindPattern, bool recursive, bool flatten, size_t *pStringLengths) { MFFindData findData; MFFind *hFind; int numFiles = 0; hFind = MFFileSystem_FindFirst(MFString::Format("%s*", pFindPattern).CStr(), &findData); if(hFind) { *pStringLengths += MFString_Length(findData.pSystemPath) + 1; } while(hFind) { if(MFString_Compare(findData.pFilename, ".") && MFString_Compare(findData.pFilename, "..") && MFString_Compare(findData.pFilename, ".svn")) { if(findData.info.attributes & MFFA_Directory) { if(recursive) { if(flatten) { MFString newPath = MFString::Format("%s%s/", pFindPattern, findData.pFilename); numFiles += MFFileSystem_GetNumEntries(newPath.CStr(), recursive, flatten, pStringLengths); } else { *pStringLengths += MFString_Length(findData.pFilename) + 1; ++numFiles; } } } else { *pStringLengths += MFString_Length(findData.pFilename) + 1; ++numFiles; } } if(!MFFileSystem_FindNext(hFind, &findData)) { MFFileSystem_FindClose(hFind); hFind = NULL; } } return numFiles; }
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; }
MFTOCEntry* MFFileSystem_BuildToc(const char *pFindPattern, MFTOCEntry *pToc, MFTOCEntry *pParent, char* &pStringCache, bool recursive, bool flatten) { MFFindData findData; MFFind *hFind; hFind = MFFileSystem_FindFirst(MFString::Format("%s*", pFindPattern).CStr(), &findData); char *pCurrentDir = pStringCache; if(hFind) { MFString_Copy(pCurrentDir, findData.pSystemPath); pStringCache += MFString_Length(findData.pSystemPath) + 1; } while(hFind) { if(MFString_Compare(findData.pFilename, ".") && MFString_Compare(findData.pFilename, "..") && MFString_Compare(findData.pFilename, ".svn")) { if(findData.info.attributes & MFFA_Directory) { if(recursive) { MFString newPath = MFString::Format("%s%s/", pFindPattern, findData.pFilename); if(flatten) { pToc = MFFileSystem_BuildToc(newPath.CStr(), pToc, pParent, pStringCache, recursive, flatten); } else { size_t stringCacheSize = 0; pToc->numChildren = MFFileSystem_GetNumEntries(newPath.CStr(), recursive, flatten, &stringCacheSize); MFString_Copy(pStringCache, findData.pFilename); pToc->pName = pStringCache; pStringCache += MFString_Length(findData.pFilename)+1; pToc->info = findData.info; pToc->pFilesysData = pCurrentDir; pToc->pParent = pParent; if (pToc->numChildren) { size_t sizeOfToc = sizeof(MFTOCEntry)*pToc->numChildren; pToc->pChildren = (MFTOCEntry*)MFHeap_Alloc(sizeOfToc + stringCacheSize); char *pNewStringCache = (char*)pToc->pChildren + sizeOfToc; MFFileSystem_BuildToc(newPath.CStr(), pToc->pChildren, pToc, pNewStringCache, recursive, flatten); } else pToc->pChildren = NULL; ++pToc; } } } else { MFString_Copy(pStringCache, findData.pFilename); pToc->pName = pStringCache; pStringCache += MFString_Length(findData.pFilename)+1; pToc->pFilesysData = pCurrentDir; pToc->pParent = pParent; pToc->pChildren = NULL; pToc->numChildren = 0; pToc->info = findData.info; ++pToc; } } if(!MFFileSystem_FindNext(hFind, &findData)) { MFFileSystem_FindClose(hFind); hFind = NULL; } } return pToc; }
MFTOCEntry* MFFileSystem_BuildToc(const char *pFindPattern, MFTOCEntry *pToc, MFTOCEntry *pParent, char* &pStringCache, bool recursive, bool flatten) { MFFindData findData; MFFind *hFind; hFind = MFFileSystem_FindFirst(MFString::Format("%s*", pFindPattern).CStr(), &findData); char *pCurrentDir = pStringCache; if(hFind) { MFString_Copy(pCurrentDir, findData.pSystemPath); pStringCache += MFString_Length(findData.pSystemPath) + 1; } while(hFind) { if(MFString_Compare(findData.pFilename, ".") && MFString_Compare(findData.pFilename, "..") && MFString_Compare(findData.pFilename, ".svn")) { if(findData.attributes & MFFA_Directory) { if(recursive) { MFString newPath = MFString::Format("%s%s/", pFindPattern, findData.pFilename); if(flatten) { pToc = MFFileSystem_BuildToc(newPath.CStr(), pToc, pParent, pStringCache, recursive, flatten); } else { size_t stringCacheSize = 0; pToc->size = MFFileSystem_GetNumEntries(newPath.CStr(), recursive, flatten, &stringCacheSize); if(pToc->size) { MFString_Copy(pStringCache, findData.pFilename); pToc->pName = pStringCache; pStringCache += MFString_Length(findData.pFilename)+1; pToc->flags = MFTF_Directory; pToc->pFilesysData = pCurrentDir; pToc->pParent = pParent; pToc->size = 0; size_t sizeOfToc = sizeof(MFTOCEntry)*pToc->size; pToc->pChild = (MFTOCEntry*)MFHeap_Alloc(sizeof(MFTOCEntry)*sizeOfToc + stringCacheSize); char *pNewStringCache = ((char*)pToc->pChild)+sizeOfToc; MFFileSystem_BuildToc(newPath.CStr(), pToc->pChild, pToc, pNewStringCache, recursive, flatten); ++pToc; } } } } else { MFString_Copy(pStringCache, findData.pFilename); pToc->pName = pStringCache; pStringCache += MFString_Length(findData.pFilename)+1; pToc->pFilesysData = pCurrentDir; pToc->pParent = pParent; pToc->pChild = NULL; MFDebug_Assert(findData.fileSize < 0x100000000LL, "Files larger than 4gb not yet supported..."); pToc->size = (uint32)findData.fileSize; pToc->flags = 0; ++pToc; } } if(!MFFileSystem_FindNext(hFind, &findData)) { MFFileSystem_FindClose(hFind); hFind = NULL; } } return pToc; }