diff --git a/src/dos/drive_cache.cpp b/src/dos/drive_cache.cpp index 44565bb8..b3ef37d7 100644 --- a/src/dos/drive_cache.cpp +++ b/src/dos/drive_cache.cpp @@ -55,16 +55,19 @@ bool SortByDirNameRev(DOS_Drive_Cache::CFileInfo* const &a, DOS_Drive_Cache::CFi DOS_Drive_Cache::DOS_Drive_Cache(void) { dirBase = new CFileInfo; - dirSearch = 0; save_dir = 0; + srchNr = 0; + for (Bit32u i=0; i=0)) return; + CreateEntry(dir,file); // Sort Lists - filelist has to be alphabetically sorted std::sort(dir->fileList.begin(), dir->fileList.end(), SortByName); @@ -142,7 +155,7 @@ void DOS_Drive_Cache::AddEntry(const char* path) void DOS_Drive_Cache::DeleteEntry(const char* path, bool ignoreLastDir) { CacheOut(path,ignoreLastDir); - if (nextEntry>0) nextEntry--; + if (dirSearch[srchNr]->nextEntry>0) dirSearch[srchNr]->nextEntry--; }; void DOS_Drive_Cache::CacheOut(const char* path, bool ignoreLastDir) @@ -180,6 +193,31 @@ bool DOS_Drive_Cache::IsCachedIn(CFileInfo* curDir) return (curDir->fileList.size()>0); }; + +bool DOS_Drive_Cache::GetShortName(const char* fullname, char* shortname) +{ + // Get Dir Info + char expand[CROSS_LEN] = {0}; + CFileInfo* curDir = FindDirInfo(fullname,expand); + + Bit16s foundNr = 0; + Bit16s low = 0; + Bit16s high = curDir->longNameList.size()-1; + Bit16s mid, res; + + while (low<=high) { + mid = (low+high)/2; + res = strcmp(fullname,curDir->longNameList[mid]->orgname); + if (res>0) low = mid+1; else + if (res<0) high = mid-1; + else { + strcpy(shortname,curDir->longNameList[mid]->shortname); + return true; + }; + } + return false; +}; + Bit16u DOS_Drive_Cache::CreateShortNameID(CFileInfo* curDir, const char* name) { Bit16s foundNr = 0; @@ -319,6 +357,7 @@ DOS_Drive_Cache::CFileInfo* DOS_Drive_Cache::FindDirInfo(const char* path, char* char* start = (char*)path; char* pos; CFileInfo* curDir = dirBase; + Bit16u id; if (save_dir && (strcmp(path,save_path)==0)) { strcpy(expandedPath,save_expanded); @@ -327,22 +366,23 @@ DOS_Drive_Cache::CFileInfo* DOS_Drive_Cache::FindDirInfo(const char* path, char* // LOG_DEBUG("DIR: Find %s",path); - // hehe, baseDir should be cached in... - if (!IsCachedIn(curDir)) { - strcpy(work,basePath); - if (OpenDir(curDir,work)) { - char buffer[CROSS_LEN]; - struct dirent* result; - strcpy(buffer,dirPath); - ReadDir(result); - strcpy(dirPath,buffer); - }; - }; - // Remove base dir path start += strlen(basePath); strcpy(expandedPath,basePath); + // hehe, baseDir should be cached in... + if (!IsCachedIn(curDir)) { + strcpy(work,basePath); + if (OpenDir(curDir,work,id)) { + char buffer[CROSS_LEN]; + struct dirent* result; + strcpy(buffer,dirPath); + ReadDir(id,result); + strcpy(dirPath,buffer); + free[id] = true; + }; + }; + do { // bool errorcheck = false; pos = strchr(start,CROSS_FILESPLIT); @@ -366,12 +406,13 @@ DOS_Drive_Cache::CFileInfo* DOS_Drive_Cache::FindDirInfo(const char* path, char* // Cut Directory, if its only part of whole path if (pos) work[(Bit32u)pos-(Bit32u)path] = 0; if (!IsCachedIn(curDir)) { - if (OpenDir(curDir,work)) { + if (OpenDir(curDir,work,id)) { char buffer[CROSS_LEN]; struct dirent* result; strcpy(buffer,dirPath); - ReadDir(result); + ReadDir(id,result); strcpy(dirPath,buffer); + free[id] = true; }; } }; @@ -389,31 +430,33 @@ DOS_Drive_Cache::CFileInfo* DOS_Drive_Cache::FindDirInfo(const char* path, char* return curDir; }; -bool DOS_Drive_Cache::OpenDir(const char* path) +bool DOS_Drive_Cache::OpenDir(const char* path, Bit16u& id) { char expand[CROSS_LEN] = {0}; CFileInfo* dir = FindDirInfo(path,expand); - if (OpenDir(dir,expand)) { - nextEntry = 0; + if (OpenDir(dir,expand,id)) { + dirSearch[id]->nextEntry = 0; return true; } return false; }; -bool DOS_Drive_Cache::OpenDir(CFileInfo* dir, char* expand) +bool DOS_Drive_Cache::OpenDir(CFileInfo* dir, char* expand, Bit16u& id) { - dirSearch = dir; + id = GetFreeID(); + dirSearch[id] = dir; // Add "/" char end[2]={CROSS_FILESPLIT,0}; if (expand[strlen(expand)-1]!=CROSS_FILESPLIT) strcat(expand,end); // open dir - if (dirSearch) { + if (dirSearch[id]) { // open dir DIR* dirp = opendir(expand); if (dirp) { // Reset it.. closedir(dirp); strcpy(dirPath,expand); + free[id] = false; return true; } }; @@ -439,27 +482,31 @@ void DOS_Drive_Cache::CreateEntry(CFileInfo* dir, const char* name) dir->outputList.push_back(info); }; -bool DOS_Drive_Cache::ReadDir(struct dirent* &result) +bool DOS_Drive_Cache::ReadDir(Bit16u id, struct dirent* &result) { - if (!IsCachedIn(dirSearch)) { + // shouldnt happen... + if (id>MAX_OPENDIRS) return false; + + if (!IsCachedIn(dirSearch[id])) { // Try to open directory DIR* dirp = opendir(dirPath); + if (!dirp) return false; // Read complete directory struct dirent* tmpres; while (tmpres = readdir(dirp)) { - CreateEntry(dirSearch,tmpres->d_name); + CreateEntry(dirSearch[id],tmpres->d_name); // Sort Lists - filelist has to be alphabetically sorted, even in between (for finding double file names) // hmpf.. bit slow probably... - std::sort(dirSearch->fileList.begin(), dirSearch->fileList.end(), SortByName); + std::sort(dirSearch[id]->fileList.begin(), dirSearch[id]->fileList.end(), SortByName); } // close dir closedir(dirp); // Output list - user defined switch (sortDirType) { - case ALPHABETICAL : std::sort(dirSearch->outputList.begin(), dirSearch->outputList.end(), SortByName); break; - case DIRALPHABETICAL : std::sort(dirSearch->outputList.begin(), dirSearch->outputList.end(), SortByDirName); break; - case ALPHABETICALREV : std::sort(dirSearch->outputList.begin(), dirSearch->outputList.end(), SortByNameRev); break; - case DIRALPHABETICALREV : std::sort(dirSearch->outputList.begin(), dirSearch->outputList.end(), SortByDirNameRev); break; + case ALPHABETICAL : std::sort(dirSearch[id]->outputList.begin(), dirSearch[id]->outputList.end(), SortByName); break; + case DIRALPHABETICAL : std::sort(dirSearch[id]->outputList.begin(), dirSearch[id]->outputList.end(), SortByDirName); break; + case ALPHABETICALREV : std::sort(dirSearch[id]->outputList.begin(), dirSearch[id]->outputList.end(), SortByNameRev); break; + case DIRALPHABETICALREV : std::sort(dirSearch[id]->outputList.begin(), dirSearch[id]->outputList.end(), SortByDirNameRev); break; }; // Info /* if (!dirp) { @@ -467,11 +514,13 @@ bool DOS_Drive_Cache::ReadDir(struct dirent* &result) return false; } else { char buffer[128]; - sprintf(buffer,"DIR: Caching in %s (%d Files)",dirPath,dirSearch->fileList.size()); + sprintf(buffer,"DIR: Caching in %s (%d Files)",dirPath,dirSearch[srchNr]->fileList.size()); LOG_DEBUG(buffer); };*/ }; - return SetResult(dirSearch, result, nextEntry); + if (SetResult(dirSearch[id], result, dirSearch[id]->nextEntry)) return true; + free[id] = true; + return false; }; bool DOS_Drive_Cache::SetResult(CFileInfo* dir, struct dirent* &result, Bit16u entryNr) @@ -484,7 +533,7 @@ bool DOS_Drive_Cache::SetResult(CFileInfo* dir, struct dirent* &result, Bit16u e // copy filename, short version strcpy(result->d_name,info->shortname); // Set to next Entry - nextEntry = entryNr+1; + dir->nextEntry = entryNr+1; return true; }; @@ -502,19 +551,21 @@ void DOS_No_Drive_Cache::SetBaseDir(const char* path) strcpy(basePath,path); } -bool DOS_No_Drive_Cache::OpenDir(const char* path) +bool DOS_No_Drive_Cache::OpenDir(const char* path, Bit16u& id) { + id = 0; strcpy(dirPath,path); if((srch_opendir=opendir(dirPath))==NULL) return false; return true; }; -bool DOS_No_Drive_Cache::ReadDir(struct dirent* &result) +bool DOS_No_Drive_Cache::ReadDir(Bit16u id, struct dirent* &result) { - if((result=readdir(srch_opendir))==NULL) { + if (!srch_opendir) return false; + if ((result=readdir(srch_opendir))==NULL) { closedir(srch_opendir); srch_opendir=NULL; return false; } return true; -}; \ No newline at end of file +}; diff --git a/src/dos/drive_local.cpp b/src/dos/drive_local.cpp index 51b0420d..88f59f5e 100644 --- a/src/dos/drive_local.cpp +++ b/src/dos/drive_local.cpp @@ -51,7 +51,7 @@ bool localDrive::FileCreate(DOS_File * * file,char * name,Bit16u attributes) { CROSS_FILENAME(newname); FILE * hand=fopen(dirCache.GetExpandName(newname),"wb+"); if (!hand) return false; - dirCache.AddEntry(newname); + dirCache.AddEntry(newname, true); /* Make the 16 bit device information */ *file=new localFile(hand,0x202); return true; @@ -98,18 +98,21 @@ bool localDrive::FileUnlink(char * name) { bool localDrive::FindFirst(char * _dir,DOS_DTA & dta) { - strcpy(srch_dir,basedir); - strcat(srch_dir,_dir); - CROSS_FILENAME(srch_dir); + char tempDir[CROSS_LEN]; + strcpy(tempDir,basedir); + strcat(tempDir,_dir); + CROSS_FILENAME(tempDir); char end[2]={CROSS_FILESPLIT,0}; - if (srch_dir[strlen(srch_dir)-1]!=CROSS_FILESPLIT) strcat(srch_dir,end); + if (tempDir[strlen(tempDir)-1]!=CROSS_FILESPLIT) strcat(tempDir,end); - if (!dirCache.OpenDir(srch_dir)) return false; + Bit16u id; + if (!dirCache.OpenDir(tempDir,id)) return false; + strcpy(srchInfo[id].srch_dir,tempDir); + dta.SetDirID(id); return FindNext(dta); } - bool localDrive::FindNext(DOS_DTA & dta) { struct dirent* dir_ent; @@ -121,12 +124,16 @@ bool localDrive::FindNext(DOS_DTA & dta) { dta.GetSearchParams(srch_attr,srch_pattern); + Bit16u id = dta.GetDirID(); + again: - if (!dirCache.ReadDir(dir_ent)) return false; + if (!dirCache.ReadDir(id,dir_ent)) { + return false; + } if(!WildFileCmp(dir_ent->d_name,srch_pattern)) goto again; - strcpy(full_name,srch_dir); + strcpy(full_name,srchInfo[id].srch_dir); strcat(full_name,dir_ent->d_name); if (stat(dirCache.GetExpandName(full_name),&stat_block)!=0) { goto again; @@ -287,7 +294,6 @@ Bit8u localDrive::GetMediaByte(void) { localDrive::localDrive(const char * startdir,Bit16u _bytes_sector,Bit8u _sectors_cluster,Bit16u _total_clusters,Bit16u _free_clusters,Bit8u _mediaid) { strcpy(basedir,startdir); sprintf(info,"local directory %s",startdir); - srch_opendir=NULL; allocation.bytes_sector=_bytes_sector; allocation.sectors_cluster=_sectors_cluster; allocation.total_clusters=_total_clusters; diff --git a/src/dos/drives.h b/src/dos/drives.h index e058b978..92d5f034 100644 --- a/src/dos/drives.h +++ b/src/dos/drives.h @@ -24,7 +24,8 @@ #include #include "dos_system.h" #include "cross.h" - + +#define MAX_OPENDIRS 16 bool WildFileCmp(const char * file, const char * wild); @@ -38,14 +39,15 @@ public: void SetBaseDir (const char* path); void SetDirSort (TDirSort sort) { sortDirType = sort; }; - bool OpenDir (const char* path); - bool ReadDir (struct dirent* &result); + bool OpenDir (const char* path, Bit16u& id); + bool ReadDir (Bit16u id, struct dirent* &result); void ExpandName (char* path); char* GetExpandName (const char* path); + bool GetShortName (const char* fullname, char* shortname); void CacheOut (const char* path, bool ignoreLastDir = false); - void AddEntry (const char* path); + void AddEntry (const char* path, bool checkExist = false); void DeleteEntry (const char* path, bool ignoreLastDir = false); class CFileInfo { @@ -56,10 +58,10 @@ public: longNameList.clear(); outputList.clear(); }; - char fullname [CROSS_LEN]; char orgname [CROSS_LEN]; char shortname [DOS_NAMELENGTH_ASCII]; bool isDir; + Bit16u nextEntry; Bit16u shortNr; Bit16u compareCount; // contents @@ -77,12 +79,11 @@ private: bool IsCachedIn (CFileInfo* dir); CFileInfo* FindDirInfo (const char* path, char* expandedPath); bool RemoveSpaces (char* str); - bool OpenDir (CFileInfo* dir, char* path); + bool OpenDir (CFileInfo* dir, char* path, Bit16u& id); void CreateEntry (CFileInfo* dir, const char* name); + Bit16u GetFreeID (void); - Bit32u nextEntry; CFileInfo* dirBase; - CFileInfo* dirSearch; char dirPath [CROSS_LEN]; char basePath [CROSS_LEN]; bool dirFirstTime; @@ -91,6 +92,11 @@ private: char save_path [CROSS_LEN]; char save_expanded [CROSS_LEN]; + Bit16u srchNr; + CFileInfo* dirSearch [MAX_OPENDIRS]; + char dirSearchName [MAX_OPENDIRS]; + bool free [MAX_OPENDIRS]; + }; class DOS_No_Drive_Cache { @@ -103,15 +109,19 @@ public: void SetBaseDir (const char* path); void SetDirSort (TDirSort sort) {}; - bool OpenDir (const char* path); - bool ReadDir (struct dirent* &result); + bool OpenDir (const char* path, Bit16u& id); + bool ReadDir (Bit16u id, struct dirent* &result); void ExpandName (char* path) {}; char* GetExpandName (const char* path) { return (char*)path; }; + bool GetShortName (const char* fullname, char* shortname) { return false; }; void CacheOut (const char* path, bool ignoreLastDir = false) {}; - void AddEntry (const char* path) {}; - void DeleteEntry (const char* path, bool ignoreLastDir = false); + void AddEntry (const char* path, bool checkExists = false) {}; + void DeleteEntry (const char* path, bool ignoreLastDir = false) {}; + + void SetCurrentEntry (Bit16u entry) {}; + Bit16u GetCurrentEntry (void) { return 0; }; public: char basePath [CROSS_LEN]; @@ -136,10 +146,14 @@ public: bool FileExists(const char* name); bool FileStat(const char* name, FileStat_Block * const stat_block); Bit8u GetMediaByte(void); + bool GetShortName(const char* fullname, char* shortname) { return dirCache.GetShortName(fullname, shortname); }; private: char basedir[CROSS_LEN]; - char srch_dir[CROSS_LEN]; - DIR * srch_opendir; + + struct { + char srch_dir[CROSS_LEN]; + } srchInfo[MAX_OPENDIRS]; + struct { Bit16u bytes_sector; Bit8u sectors_cluster; @@ -147,7 +161,7 @@ private: Bit16u free_clusters; Bit8u mediaid; } allocation; - DOS_Drive_Cache dirCache; + DOS_Drive_Cache dirCache; }; struct VFILE_Block;