added directory cache
Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@630
This commit is contained in:
parent
a1f52fbd1d
commit
fb2896a653
3 changed files with 578 additions and 31 deletions
462
src/dos/drive_cache.cpp
Normal file
462
src/dos/drive_cache.cpp
Normal file
|
@ -0,0 +1,462 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) 2002-2003 The DOSBox Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "drives.h"
|
||||
#include "dos_inc.h"
|
||||
#include "dirent.h"
|
||||
#include "support.h"
|
||||
|
||||
// STL stuff
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
bool SortByName(DOS_Drive_Cache::CFileInfo* const &a, DOS_Drive_Cache::CFileInfo* const &b)
|
||||
{
|
||||
return strcmp(a->shortname,b->shortname)<0;
|
||||
};
|
||||
|
||||
bool SortByNameRev(DOS_Drive_Cache::CFileInfo* const &a, DOS_Drive_Cache::CFileInfo* const &b)
|
||||
{
|
||||
return strcmp(a->shortname,b->shortname)>0;
|
||||
};
|
||||
|
||||
bool SortByDirName(DOS_Drive_Cache::CFileInfo* const &a, DOS_Drive_Cache::CFileInfo* const &b)
|
||||
{
|
||||
// Directories first...
|
||||
if (a->isDir!=b->isDir) return (a->isDir>b->isDir);
|
||||
return strcmp(a->shortname,b->shortname)<0;
|
||||
};
|
||||
|
||||
bool SortByDirNameRev(DOS_Drive_Cache::CFileInfo* const &a, DOS_Drive_Cache::CFileInfo* const &b)
|
||||
{
|
||||
// Directories first...
|
||||
if (a->isDir!=b->isDir) return (a->isDir>b->isDir);
|
||||
return strcmp(a->shortname,b->shortname)>0;
|
||||
};
|
||||
|
||||
DOS_Drive_Cache::DOS_Drive_Cache(void)
|
||||
{
|
||||
dirBase = new CFileInfo;
|
||||
dirSearch = 0;
|
||||
save_dir = 0;
|
||||
SetDirSort(DIRALPHABETICAL);
|
||||
};
|
||||
|
||||
DOS_Drive_Cache::DOS_Drive_Cache(const char* path)
|
||||
{
|
||||
dirBase = new CFileInfo;
|
||||
dirSearch = 0;
|
||||
save_dir = 0;
|
||||
SetDirSort(DIRALPHABETICAL);
|
||||
SetBaseDir(path);
|
||||
};
|
||||
|
||||
DOS_Drive_Cache::~DOS_Drive_Cache(void)
|
||||
{
|
||||
delete dirBase; dirBase = 0;
|
||||
};
|
||||
|
||||
void DOS_Drive_Cache::SetBaseDir(const char* baseDir)
|
||||
{
|
||||
strcpy(dirBase->fullname,baseDir);
|
||||
if (OpenDir(baseDir)) {
|
||||
struct dirent result;
|
||||
struct stat status;
|
||||
ReadDir(&result,&status);
|
||||
};
|
||||
};
|
||||
|
||||
void DOS_Drive_Cache::ExpandName(char* path)
|
||||
{
|
||||
strcpy(path,GetExpandName(path));
|
||||
};
|
||||
|
||||
char* DOS_Drive_Cache::GetExpandName(const char* path)
|
||||
{
|
||||
static char work [CROSS_LEN];
|
||||
char dir [CROSS_LEN];
|
||||
|
||||
work[0] = 0;
|
||||
strcpy (dir,path);
|
||||
|
||||
char* pos = strrchr(path,CROSS_FILESPLIT);
|
||||
|
||||
if (pos) dir[pos-path+1] = 0;
|
||||
CFileInfo* dirInfo = FindDirInfo(dir, work);
|
||||
|
||||
if (pos) {
|
||||
// Last Entry = File
|
||||
strcpy(dir,pos+1);
|
||||
if (strchr(dir,'~')) GetLongName(dirInfo, dir);
|
||||
strcat(work,dir);
|
||||
}
|
||||
return work;
|
||||
};
|
||||
|
||||
void DOS_Drive_Cache::AddEntry(const char* path)
|
||||
{
|
||||
// Get Last part...
|
||||
char file [CROSS_LEN];
|
||||
char expand [CROSS_LEN];
|
||||
|
||||
CFileInfo* dir = FindDirInfo(path,expand);
|
||||
char* pos = strrchr(path,CROSS_FILESPLIT);
|
||||
|
||||
if (pos) {
|
||||
strcpy(file,pos+1);
|
||||
CreateEntry(dir,file);
|
||||
// Sort Lists - filelist has to be alphabetically sorted
|
||||
std::sort(dir->fileList.begin(), dir->fileList.end(), SortByName);
|
||||
// Output list - user defined
|
||||
switch (sortDirType) {
|
||||
case ALPHABETICAL : std::sort(dir->outputList.begin(), dir->outputList.end(), SortByName); break;
|
||||
case DIRALPHABETICAL : std::sort(dir->outputList.begin(), dir->outputList.end(), SortByDirName); break;
|
||||
case ALPHABETICALREV : std::sort(dir->outputList.begin(), dir->outputList.end(), SortByNameRev); break;
|
||||
case DIRALPHABETICALREV : std::sort(dir->outputList.begin(), dir->outputList.end(), SortByDirNameRev); break;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
void DOS_Drive_Cache::CacheOut(const char* path, bool ignoreLastDir)
|
||||
{
|
||||
char expand[CROSS_LEN] = { 0 };
|
||||
CFileInfo* dir;
|
||||
|
||||
if (ignoreLastDir) {
|
||||
char tmp[CROSS_LEN] = { 0 };
|
||||
Bit32s len = strrchr(path,CROSS_FILESPLIT) - path;
|
||||
if (len>0) {
|
||||
strncpy(tmp,path,len);
|
||||
tmp[len] = 0;
|
||||
} else {
|
||||
strcpy(tmp,path);
|
||||
}
|
||||
dir = FindDirInfo(tmp,expand);
|
||||
} else {
|
||||
dir = FindDirInfo(path,expand);
|
||||
}
|
||||
// LOG_DEBUG("DIR: Caching out %s : dir %s",expand,dir->fullname);
|
||||
// delete file objects...
|
||||
for(Bit32u i=0; i<dir->fileList.size(); i++) delete dir->fileList[i];
|
||||
// clear lists
|
||||
dir->fileList.clear();
|
||||
dir->longNameList.clear();
|
||||
dir->outputList.clear();
|
||||
dir->shortNr = 0;
|
||||
save_dir = 0;
|
||||
nextEntry = 0;
|
||||
};
|
||||
|
||||
bool DOS_Drive_Cache::IsCachedIn(CFileInfo* curDir)
|
||||
{
|
||||
return (curDir->fileList.size()>0);
|
||||
};
|
||||
|
||||
Bit16u DOS_Drive_Cache::CreateShortNameID(CFileInfo* curDir, const char* name)
|
||||
{
|
||||
Bit16s foundNr = 0;
|
||||
Bit16s low = 0;
|
||||
Bit16s high = curDir->longNameList.size()-1;
|
||||
Bit16s mid, res;
|
||||
|
||||
CFileInfo* test;
|
||||
|
||||
while (low<=high) {
|
||||
mid = (low+high)/2;
|
||||
test = curDir->longNameList[mid];
|
||||
res = strncmp(name,curDir->longNameList[mid]->shortname,curDir->longNameList[mid]->compareCount);
|
||||
if (res>0) low = mid+1; else
|
||||
if (res<0) high = mid-1;
|
||||
else {
|
||||
// any more same x chars in next entries ?
|
||||
do {
|
||||
foundNr = curDir->longNameList[mid]->shortNr;
|
||||
mid++;
|
||||
} while(mid<curDir->longNameList.size() && (strncmp(name,curDir->longNameList[mid]->shortname,curDir->longNameList[mid]->compareCount)==0));
|
||||
break;
|
||||
};
|
||||
}
|
||||
return foundNr+1;
|
||||
};
|
||||
|
||||
Bit16s DOS_Drive_Cache::GetLongName(CFileInfo* curDir, char* shortName)
|
||||
{
|
||||
// Search long name and return array number of element
|
||||
Bit16s low = 0;
|
||||
Bit16s high = curDir->fileList.size()-1;
|
||||
Bit16s mid,res;
|
||||
while (low<=high) {
|
||||
mid = (low+high)/2;
|
||||
CFileInfo* test = curDir->fileList[mid];
|
||||
res = strcmp(shortName,curDir->fileList[mid]->shortname);
|
||||
if (res>0) low = mid+1; else
|
||||
if (res<0) high = mid-1; else
|
||||
{ // Found
|
||||
// strcpy(shortName,curDir->fileList[mid]->fullname);
|
||||
strcpy(shortName,curDir->fileList[mid]->orgname);
|
||||
return mid;
|
||||
};
|
||||
}
|
||||
// not available
|
||||
return -1;
|
||||
};
|
||||
|
||||
Bit16s DOS_Drive_Cache::RemoveSpaces(char* str)
|
||||
// Removes all spaces
|
||||
// return length of string upto first '.'
|
||||
{
|
||||
char* curpos = str;
|
||||
char* chkpos = str;
|
||||
Bit16s len = -1;
|
||||
while (*chkpos!=0) {
|
||||
if (*chkpos=='.') { if (len<0) len = curpos - str; };
|
||||
if (*chkpos==' ') chkpos++; else *curpos++ = *chkpos++;
|
||||
}
|
||||
*curpos = 0;
|
||||
if (len<0) len = curpos - str;
|
||||
return len;
|
||||
};
|
||||
|
||||
void DOS_Drive_Cache::CreateShortName(CFileInfo* curDir, CFileInfo* info)
|
||||
{
|
||||
Bit16s len = 0;
|
||||
Bit16s lenExt = 0;
|
||||
char tmpName[CROSS_LEN];
|
||||
|
||||
// Remove Spaces
|
||||
strcpy(tmpName,info->fullname);
|
||||
len = RemoveSpaces(tmpName);
|
||||
|
||||
// Get Length of filename
|
||||
char* pos = strchr(tmpName,'.');
|
||||
if (pos) {
|
||||
len = (Bit16u)(pos - tmpName);
|
||||
// Get Length of extension
|
||||
lenExt = strlen(pos)-1;
|
||||
} else
|
||||
len = strlen(tmpName);
|
||||
|
||||
// Should shortname version be created ?
|
||||
bool createShort = (len>8) || (lenExt>3);
|
||||
// if (!createShort) {
|
||||
// char buffer[CROSS_LEN];
|
||||
// strcpy(buffer,tmpName);
|
||||
// createShort = (GetLongName(curDir,buffer)>=0);
|
||||
// }
|
||||
|
||||
if (createShort) {
|
||||
// Create number
|
||||
char buffer[8];
|
||||
info->shortNr = CreateShortNameID(curDir,tmpName);
|
||||
sprintf(buffer,"%d",info->shortNr);
|
||||
// Copy first letters
|
||||
Bit16u tocopy;
|
||||
if (len+strlen(buffer)>8) tocopy = 8 - strlen(buffer) - 1;
|
||||
else tocopy = len;
|
||||
strncpy(info->shortname,tmpName,tocopy);
|
||||
info->shortname[tocopy] = 0;
|
||||
// Copy number
|
||||
strcat(info->shortname,"~");
|
||||
strcat(info->shortname,buffer);
|
||||
// Create compare Count
|
||||
info->compareCount = tocopy;
|
||||
// Add (and cut) Extension, if available
|
||||
if (pos) {
|
||||
// Step to last extension...
|
||||
pos = strrchr(tmpName, '.');
|
||||
// add extension
|
||||
strncat(info->shortname,pos,4);
|
||||
info->shortname[DOS_NAMELENGTH] = 0;
|
||||
};
|
||||
// Put it in longname list...
|
||||
curDir->longNameList.push_back(info);
|
||||
std::sort(curDir->longNameList.begin(), curDir->longNameList.end(), SortByName);
|
||||
} else {
|
||||
strcpy(info->shortname,tmpName);
|
||||
}
|
||||
};
|
||||
|
||||
DOS_Drive_Cache::CFileInfo* DOS_Drive_Cache::FindDirInfo(const char* path, char* expandedPath)
|
||||
{
|
||||
// statics
|
||||
static char split[2] = { CROSS_FILESPLIT,0 };
|
||||
|
||||
char dir [CROSS_LEN];
|
||||
char work [CROSS_LEN];
|
||||
char* start = (char*)path;
|
||||
char* pos;
|
||||
CFileInfo* curDir = dirBase;
|
||||
|
||||
if (save_dir && (strcmp(path,save_path)==0)) {
|
||||
strcpy(expandedPath,save_expanded);
|
||||
return save_dir;
|
||||
};
|
||||
|
||||
// LOG_DEBUG("DIR: Find %s",path);
|
||||
|
||||
// Remove base dir path
|
||||
start += strlen(dirBase->fullname);
|
||||
strcpy(expandedPath,dirBase->fullname);
|
||||
|
||||
do {
|
||||
// bool errorcheck = false;
|
||||
pos = strchr(start,CROSS_FILESPLIT);
|
||||
if (pos) { strncpy(dir,start,pos-start); dir[pos-start] = 0; /*errorcheck = true;*/ }
|
||||
else { strcpy(dir,start); };
|
||||
|
||||
// Path found
|
||||
Bit16s nextDir = GetLongName(curDir,dir);
|
||||
strcat(expandedPath,dir);
|
||||
|
||||
// Error check
|
||||
// if ((errorcheck) && (nextDir<0)) {
|
||||
// LOG_DEBUG("DIR: Error: %s not found.",expandedPath);
|
||||
// };
|
||||
|
||||
// Follow Directory
|
||||
if ((nextDir>=0) && curDir->fileList[nextDir]->isDir) {
|
||||
curDir = curDir->fileList[nextDir];
|
||||
strcpy (curDir->fullname,dir);
|
||||
strcpy (work,path);
|
||||
// Cut Directory, if its only part of whole path
|
||||
if (pos) work[(Bit32u)pos-(Bit32u)path] = 0;
|
||||
if (!IsCachedIn(curDir)) {
|
||||
if (OpenDir(curDir,work)) {
|
||||
struct dirent result;
|
||||
struct stat status;
|
||||
ReadDir(&result,&status);
|
||||
};
|
||||
}
|
||||
};
|
||||
if (pos) {
|
||||
strcat(expandedPath,split);
|
||||
start = pos+1;
|
||||
}
|
||||
} while (pos);
|
||||
|
||||
// Save last result for faster access next time
|
||||
strcpy(save_path,path);
|
||||
strcpy(save_expanded,expandedPath);
|
||||
save_dir = curDir;
|
||||
|
||||
return curDir;
|
||||
};
|
||||
|
||||
bool DOS_Drive_Cache::OpenDir(const char* path)
|
||||
{
|
||||
char expand[CROSS_LEN] = {0};
|
||||
CFileInfo* dir = FindDirInfo(path,expand);
|
||||
return OpenDir(dir,expand);
|
||||
};
|
||||
|
||||
bool DOS_Drive_Cache::OpenDir(CFileInfo* dir, char* expand)
|
||||
{
|
||||
dirSearch = dir;
|
||||
// Add "/"
|
||||
char end[2]={CROSS_FILESPLIT,0};
|
||||
if (expand[strlen(expand)-1]!=CROSS_FILESPLIT) strcat(expand,end);
|
||||
// open dir
|
||||
if (dirSearch) {
|
||||
// open dir
|
||||
DIR* dirp = opendir(expand);
|
||||
if (dirp) {
|
||||
dirFirstTime = true;
|
||||
closedir(dirp);
|
||||
strcpy(dirPath,expand);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
return false;
|
||||
};
|
||||
|
||||
void DOS_Drive_Cache::CreateEntry(CFileInfo* dir, const char* name)
|
||||
{
|
||||
struct stat status;
|
||||
CFileInfo* info = new CFileInfo;
|
||||
strcpy(info->fullname,name);
|
||||
strcpy(info->orgname ,name);
|
||||
// always upcase
|
||||
upcase(info->fullname);
|
||||
info->shortNr = 0;
|
||||
// Read and copy file stats
|
||||
char buffer[CROSS_LEN];
|
||||
strcpy(buffer,dirPath);
|
||||
strcat(buffer,info->fullname);
|
||||
stat (buffer,&status);
|
||||
memcpy(&info->status,&status,sizeof(status));
|
||||
info->isDir = (S_ISDIR(status.st_mode)>0);
|
||||
// Check for long filenames...
|
||||
CreateShortName(dir, info);
|
||||
// Put file in lists
|
||||
dir->fileList.push_back(info);
|
||||
dir->outputList.push_back(info);
|
||||
};
|
||||
|
||||
bool DOS_Drive_Cache::ReadDir(struct dirent* result, struct stat *status)
|
||||
{
|
||||
if (dirFirstTime) {
|
||||
if (!IsCachedIn(dirSearch)) {
|
||||
// Try to open directory
|
||||
DIR* dirp = opendir(dirPath);
|
||||
if (!dirp) {
|
||||
// LOG_DEBUG("DIR: Error Caching in %s",dirPath);
|
||||
return false;
|
||||
} else {
|
||||
// LOG_DEBUG("DIR: Caching in %s",dirPath);
|
||||
};
|
||||
// Read complete directory
|
||||
struct dirent* tmpres;
|
||||
while (tmpres = readdir(dirp)) {
|
||||
CreateEntry(dirSearch,tmpres->d_name);
|
||||
}
|
||||
// close dir
|
||||
closedir(dirp);
|
||||
// Sort Lists - filelist has to be alphabetically sorted
|
||||
std::sort(dirSearch->fileList.begin(), dirSearch->fileList.end(), SortByName);
|
||||
// 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;
|
||||
};
|
||||
} else {
|
||||
dirFirstTime=false;
|
||||
}
|
||||
// Reset it..
|
||||
nextEntry = 0;
|
||||
};
|
||||
return SetResult(dirSearch, result, status, nextEntry);
|
||||
};
|
||||
|
||||
bool DOS_Drive_Cache::SetResult(CFileInfo* dir, struct dirent* result, struct stat* status, Bit16u entryNr)
|
||||
{
|
||||
if (entryNr>=dir->outputList.size()) return false;
|
||||
CFileInfo* info = dir->outputList[entryNr];
|
||||
// copy filename, short version
|
||||
strcpy(result->d_name,info->shortname);
|
||||
// copy file status
|
||||
memcpy(status,&info->status,sizeof(info->status));
|
||||
// Set to next Entry
|
||||
nextEntry = entryNr+1;
|
||||
return true;
|
||||
};
|
||||
|
|
@ -49,8 +49,9 @@ bool localDrive::FileCreate(DOS_File * * file,char * name,Bit16u attributes) {
|
|||
strcpy(newname,basedir);
|
||||
strcat(newname,name);
|
||||
CROSS_FILENAME(newname);
|
||||
FILE * hand=fopen(newname,"wb+");
|
||||
FILE * hand=fopen(dirCache.GetExpandName(newname),"wb+");
|
||||
if (!hand) return false;
|
||||
dirCache.AddEntry(newname);
|
||||
/* Make the 16 bit device information */
|
||||
*file=new localFile(hand,0x202);
|
||||
return true;
|
||||
|
@ -59,9 +60,9 @@ bool localDrive::FileCreate(DOS_File * * file,char * name,Bit16u attributes) {
|
|||
bool localDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) {
|
||||
char * type;
|
||||
switch (flags) {
|
||||
case OPEN_READ:type="rb";break;
|
||||
case OPEN_WRITE:type="rb+";break;
|
||||
case OPEN_READWRITE:type="rb+";break;
|
||||
case OPEN_READ:type="rb"; break;
|
||||
case OPEN_WRITE:type="rb+"; break;
|
||||
case OPEN_READWRITE:type="rb+"; break;
|
||||
default:
|
||||
//TODO FIX IT
|
||||
type="rb+";
|
||||
|
@ -72,10 +73,13 @@ bool localDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) {
|
|||
strcpy(newname,basedir);
|
||||
strcat(newname,name);
|
||||
CROSS_FILENAME(newname);
|
||||
dirCache.ExpandName(newname);
|
||||
|
||||
FILE * hand=fopen(newname,type);
|
||||
Bit32u err=errno;
|
||||
if (!hand) return false;
|
||||
*file=new localFile(hand,0x202);
|
||||
// (*file)->SetFileName(newname);
|
||||
return true;
|
||||
};
|
||||
|
||||
|
@ -84,54 +88,59 @@ bool localDrive::FileUnlink(char * name) {
|
|||
strcpy(newname,basedir);
|
||||
strcat(newname,name);
|
||||
CROSS_FILENAME(newname);
|
||||
if (!unlink(newname)) return true;
|
||||
if (!unlink(dirCache.GetExpandName(newname))) {
|
||||
dirCache.CacheOut(newname);
|
||||
return true;
|
||||
};
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
bool localDrive::FindFirst(char * _dir,DOS_DTA & dta) {
|
||||
if (srch_opendir) closedir(srch_opendir);
|
||||
|
||||
strcpy(srch_dir,basedir);
|
||||
strcat(srch_dir,_dir);
|
||||
CROSS_FILENAME(srch_dir);
|
||||
|
||||
char end[2]={CROSS_FILESPLIT,0};
|
||||
if (srch_dir[strlen(srch_dir)-1]!=CROSS_FILESPLIT) strcat(srch_dir,end);
|
||||
if((srch_opendir=opendir(srch_dir))==NULL) return false;
|
||||
|
||||
if (!dirCache.OpenDir(srch_dir)) return false;
|
||||
return FindNext(dta);
|
||||
}
|
||||
|
||||
|
||||
bool localDrive::FindNext(DOS_DTA & dta) {
|
||||
struct dirent * dir_ent;
|
||||
|
||||
struct dirent dir_ent;
|
||||
struct stat stat_block;
|
||||
char full_name[CROSS_LEN];
|
||||
|
||||
Bit8u srch_attr;char srch_pattern[DOS_NAMELENGTH_ASCII];
|
||||
Bit8u find_attr;
|
||||
|
||||
if(!srch_opendir) return false;
|
||||
|
||||
dta.GetSearchParams(srch_attr,srch_pattern);
|
||||
again:
|
||||
if((dir_ent=readdir(srch_opendir))==NULL) {
|
||||
closedir(srch_opendir);
|
||||
srch_opendir=NULL;
|
||||
return false;
|
||||
}
|
||||
if(!WildFileCmp(dir_ent->d_name,srch_pattern)) goto again;
|
||||
strcpy(full_name,srch_dir);
|
||||
strcat(full_name,dir_ent->d_name);
|
||||
if(stat(full_name,&stat_block)!=0){
|
||||
goto again;
|
||||
}
|
||||
|
||||
again:
|
||||
if (!dirCache.ReadDir(&dir_ent,&stat_block)) return false;
|
||||
|
||||
if(!WildFileCmp(dir_ent.d_name,srch_pattern)) goto again;
|
||||
|
||||
if(S_ISDIR(stat_block.st_mode)) find_attr=DOS_ATTR_DIRECTORY;
|
||||
else find_attr=DOS_ATTR_ARCHIVE;
|
||||
if (~srch_attr & find_attr & (DOS_ATTR_DIRECTORY | DOS_ATTR_HIDDEN | DOS_ATTR_SYSTEM)) goto again;
|
||||
|
||||
if(S_ISDIR(stat_block.st_mode)) find_attr=DOS_ATTR_DIRECTORY;
|
||||
else find_attr=DOS_ATTR_ARCHIVE;
|
||||
if (~srch_attr & find_attr & (DOS_ATTR_DIRECTORY | DOS_ATTR_HIDDEN | DOS_ATTR_SYSTEM)) goto again;
|
||||
|
||||
/*file is okay, setup everything to be copied in DTA Block */
|
||||
char find_name[DOS_NAMELENGTH_ASCII];Bit16u find_date,find_time;Bit32u find_size;
|
||||
if(strlen(dir_ent->d_name)<DOS_NAMELENGTH_ASCII){
|
||||
strcpy(find_name,dir_ent->d_name);
|
||||
|
||||
if(strlen(dir_ent.d_name)<DOS_NAMELENGTH_ASCII){
|
||||
strcpy(find_name,dir_ent.d_name);
|
||||
upcase(find_name);
|
||||
} else strcpy(find_name,"LONGNAME.ERR");
|
||||
}
|
||||
|
||||
find_size=(Bit32u) stat_block.st_size;
|
||||
struct tm *time;
|
||||
if((time=localtime(&stat_block.st_mtime))!=0){
|
||||
|
@ -150,6 +159,7 @@ bool localDrive::GetFileAttr(char * name,Bit16u * attr) {
|
|||
strcpy(newname,basedir);
|
||||
strcat(newname,name);
|
||||
CROSS_FILENAME(newname);
|
||||
dirCache.ExpandName(newname);
|
||||
FILE * hand=fopen(newname,"rb");
|
||||
if (hand) {
|
||||
fclose(hand);
|
||||
|
@ -166,10 +176,11 @@ bool localDrive::MakeDir(char * dir) {
|
|||
strcat(newdir,dir);
|
||||
CROSS_FILENAME(newdir);
|
||||
#if defined (WIN32) /* MS Visual C++ */
|
||||
int temp=mkdir(newdir);
|
||||
int temp=mkdir(dirCache.GetExpandName(newdir));
|
||||
#else
|
||||
int temp=mkdir(newdir,0700);
|
||||
int temp=mkdir(dirCache.GetExpandName(newdir),0700);
|
||||
#endif
|
||||
if (temp==0) dirCache.CacheOut(newdir,true);
|
||||
// if dir already exists, return success too.
|
||||
return (temp==0) || ((temp!=0) && (errno==EEXIST));
|
||||
}
|
||||
|
@ -179,7 +190,8 @@ bool localDrive::RemoveDir(char * dir) {
|
|||
strcpy(newdir,basedir);
|
||||
strcat(newdir,dir);
|
||||
CROSS_FILENAME(newdir);
|
||||
int temp=rmdir(newdir);
|
||||
int temp=rmdir(dirCache.GetExpandName(newdir));
|
||||
if (temp==0) dirCache.CacheOut(newdir,true);
|
||||
return (temp==0);
|
||||
}
|
||||
|
||||
|
@ -188,6 +200,7 @@ bool localDrive::TestDir(char * dir) {
|
|||
strcpy(newdir,basedir);
|
||||
strcat(newdir,dir);
|
||||
CROSS_FILENAME(newdir);
|
||||
dirCache.ExpandName(newdir);
|
||||
// Skip directory test, if "\"
|
||||
Bit16u len = strlen(newdir);
|
||||
if ((len>0) && (newdir[len-1]!='\\')) {
|
||||
|
@ -209,7 +222,8 @@ bool localDrive::Rename(char * oldname,char * newname) {
|
|||
strcpy(newnew,basedir);
|
||||
strcat(newnew,newname);
|
||||
CROSS_FILENAME(newnew);
|
||||
int temp=rename(newold,newnew);
|
||||
int temp=rename(dirCache.GetExpandName(newold),dirCache.GetExpandName(newnew));
|
||||
if (temp==0) dirCache.CacheOut(newnew);
|
||||
return (temp==0);
|
||||
|
||||
};
|
||||
|
@ -229,6 +243,7 @@ bool localDrive::FileExists(const char* name) {
|
|||
strcpy(newname,basedir);
|
||||
strcat(newname,name);
|
||||
CROSS_FILENAME(newname);
|
||||
dirCache.ExpandName(newname);
|
||||
FILE* Temp=fopen(newname,"rb");
|
||||
if(Temp==NULL) return false;
|
||||
fclose(Temp);
|
||||
|
@ -240,6 +255,7 @@ bool localDrive::FileStat(const char* name, FileStat_Block * const stat_block) {
|
|||
strcpy(newname,basedir);
|
||||
strcat(newname,name);
|
||||
CROSS_FILENAME(newname);
|
||||
dirCache.ExpandName(newname);
|
||||
struct stat temp_stat;
|
||||
if(stat(newname,&temp_stat)!=0) return false;
|
||||
/* Convert the stat to a FileStat */
|
||||
|
@ -268,6 +284,8 @@ localDrive::localDrive(const char * startdir,Bit16u _bytes_sector,Bit8u _sectors
|
|||
allocation.total_clusters=_total_clusters;
|
||||
allocation.free_clusters=_free_clusters;
|
||||
allocation.mediaid=_mediaid;
|
||||
|
||||
dirCache.SetBaseDir(basedir);
|
||||
}
|
||||
|
||||
|
||||
|
@ -312,6 +330,7 @@ bool localFile::Seek(Bit32u * pos,Bit32u type) {
|
|||
}
|
||||
|
||||
bool localFile::Close() {
|
||||
|
||||
fclose(fhandle);
|
||||
return true;
|
||||
}
|
||||
|
@ -319,7 +338,7 @@ bool localFile::Close() {
|
|||
Bit16u localFile::GetInformation(void) {
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
|
||||
localFile::localFile(FILE * handle,Bit16u devinfo) {
|
||||
fhandle=handle;
|
||||
|
|
|
@ -21,12 +21,77 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <vector>
|
||||
#include "dos_system.h"
|
||||
#include "cross.h"
|
||||
|
||||
|
||||
bool WildFileCmp(const char * file, const char * wild);
|
||||
|
||||
class DOS_Drive_Cache {
|
||||
public:
|
||||
DOS_Drive_Cache (void);
|
||||
DOS_Drive_Cache (const char* path);
|
||||
~DOS_Drive_Cache (void);
|
||||
|
||||
typedef enum TDirSort { NOSORT, ALPHABETICAL, DIRALPHABETICAL, ALPHABETICALREV, DIRALPHABETICALREV };
|
||||
|
||||
void SetBaseDir (const char* path);
|
||||
void SetDirSort (TDirSort sort) { sortDirType = sort; };
|
||||
bool OpenDir (const char* path);
|
||||
bool ReadDir (struct dirent* result,struct stat* status);
|
||||
|
||||
void ExpandName (char* path);
|
||||
char* GetExpandName (const char* path);
|
||||
|
||||
void CacheOut (const char* path, bool ignoreLastDir = false);
|
||||
void AddEntry (const char* path);
|
||||
|
||||
class CFileInfo {
|
||||
public:
|
||||
~CFileInfo(void) {
|
||||
for (Bit32u i=0; i<fileList.size(); i++) delete fileList[i];
|
||||
fileList.clear();
|
||||
longNameList.clear();
|
||||
outputList.clear();
|
||||
};
|
||||
char fullname [CROSS_LEN];
|
||||
char orgname [CROSS_LEN];
|
||||
char shortname [DOS_NAMELENGTH_ASCII];
|
||||
bool isDir;
|
||||
Bit16u shortNr;
|
||||
Bit16u compareCount;
|
||||
struct stat status;
|
||||
// contents
|
||||
std::vector<CFileInfo*> fileList;
|
||||
std::vector<CFileInfo*> longNameList;
|
||||
std::vector<CFileInfo*> outputList;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
Bit16s GetLongName (CFileInfo* info, char* shortname);
|
||||
void CreateShortName (CFileInfo* dir, CFileInfo* info);
|
||||
Bit16u CreateShortNameID (CFileInfo* dir, const char* name);
|
||||
bool SetResult (CFileInfo* dir, struct dirent* result, struct stat* status, Bit16u entryNr);
|
||||
bool IsCachedIn (CFileInfo* dir);
|
||||
CFileInfo* FindDirInfo (const char* path, char* expandedPath);
|
||||
Bit16s RemoveSpaces (char* str);
|
||||
bool OpenDir (CFileInfo* dir, char* path);
|
||||
void CreateEntry (CFileInfo* dir, const char* name);
|
||||
|
||||
Bit32u nextEntry;
|
||||
CFileInfo* dirBase;
|
||||
CFileInfo* dirSearch;
|
||||
char dirPath [CROSS_LEN];
|
||||
bool dirFirstTime;
|
||||
TDirSort sortDirType;
|
||||
CFileInfo* save_dir;
|
||||
char save_path [CROSS_LEN];
|
||||
char save_expanded [CROSS_LEN];
|
||||
|
||||
};
|
||||
|
||||
class localDrive : public DOS_Drive {
|
||||
public:
|
||||
localDrive(const char * startdir,Bit16u _bytes_sector,Bit8u _sectors_cluster,Bit16u _total_clusters,Bit16u _free_clusters,Bit8u _mediaid);
|
||||
|
@ -55,6 +120,7 @@ private:
|
|||
Bit16u free_clusters;
|
||||
Bit8u mediaid;
|
||||
} allocation;
|
||||
DOS_Drive_Cache dirCache;
|
||||
};
|
||||
|
||||
struct VFILE_Block;
|
||||
|
|
Loading…
Add table
Reference in a new issue