Added support for multiple findfirst/findnext at the same time.
Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@664
This commit is contained in:
parent
50385d3c05
commit
e727664414
3 changed files with 139 additions and 68 deletions
|
@ -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<MAX_OPENDIRS; i++) { dirSearch[i] = 0; free[i] = true; };
|
||||
SetDirSort(DIRALPHABETICAL);
|
||||
|
||||
};
|
||||
|
||||
DOS_Drive_Cache::DOS_Drive_Cache(const char* path)
|
||||
{
|
||||
dirBase = new CFileInfo;
|
||||
dirSearch = 0;
|
||||
save_dir = 0;
|
||||
srchNr = 0;
|
||||
for (Bit32u i=0; i<MAX_OPENDIRS; i++) { dirSearch[i] = 0; free[i] = true; };
|
||||
SetDirSort(DIRALPHABETICAL);
|
||||
SetBaseDir(path);
|
||||
};
|
||||
|
@ -72,14 +75,23 @@ DOS_Drive_Cache::DOS_Drive_Cache(const char* path)
|
|||
DOS_Drive_Cache::~DOS_Drive_Cache(void)
|
||||
{
|
||||
delete dirBase; dirBase = 0;
|
||||
for (Bit32u i=0; i<MAX_OPENDIRS; i++) dirSearch[i] = 0;
|
||||
};
|
||||
|
||||
Bit16u DOS_Drive_Cache::GetFreeID(void)
|
||||
{
|
||||
for (Bit32u i=0; i<MAX_OPENDIRS; i++) if (free[i]) return i;
|
||||
LOG_ERROR("DIRCACHE: Too many open directorys!");
|
||||
return 0;
|
||||
};
|
||||
|
||||
void DOS_Drive_Cache::SetBaseDir(const char* baseDir)
|
||||
{
|
||||
Bit16u id;
|
||||
strcpy(basePath,baseDir);
|
||||
if (OpenDir(baseDir)) {
|
||||
if (OpenDir(baseDir,id)) {
|
||||
struct dirent* result;
|
||||
ReadDir(result);
|
||||
ReadDir(id,result);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -110,9 +122,8 @@ char* DOS_Drive_Cache::GetExpandName(const char* path)
|
|||
return work;
|
||||
};
|
||||
|
||||
void DOS_Drive_Cache::AddEntry(const char* path)
|
||||
void DOS_Drive_Cache::AddEntry(const char* path, bool checkExists)
|
||||
{
|
||||
// FIXME: Code doesnt seem to work with arena ??? Why is that ?
|
||||
// Get Last part...
|
||||
char file [CROSS_LEN];
|
||||
char expand [CROSS_LEN];
|
||||
|
@ -122,7 +133,9 @@ void DOS_Drive_Cache::AddEntry(const char* path)
|
|||
|
||||
if (pos) {
|
||||
strcpy(file,pos+1);
|
||||
|
||||
// Check if file already exists, then dont add new entry...
|
||||
if (checkExists && (GetLongName(dir,file)>=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;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
#include <vector>
|
||||
#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;
|
||||
|
|
Loading…
Add table
Reference in a new issue