1
0
Fork 0

Improve memory safety in the DOS Drive Cache class

- Fix Bitu printf format type
- Check a pointer prior to dereferencing it
- Prevent writing one-beyond the last index
- Replace strcpy with with helper safe_strcpy, provided by @dreamer - thank you!
- Replace strcat with strncat
- Add constructor intializers for scalars and arrays
- Initialize and replace 0-value pointers with nullptr
- Pass in the buffer length when strncpy'ing into a function variable
This commit is contained in:
krcroft 2019-12-05 23:24:15 -08:00 committed by Patryk Obara
parent 88cdd8d3a0
commit cff6b05559
4 changed files with 200 additions and 115 deletions

View file

@ -130,6 +130,8 @@ public:
void Flush(void);
FILE * fhandle; //todo handle this properly
private:
localFile(const localFile&); // prevent copying
localFile& operator= (const localFile&); // prevent assignment
bool read_only_medium;
enum { NONE,READ,WRITE } last_action;
};
@ -172,11 +174,17 @@ public:
class CFileInfo {
public:
CFileInfo(void) {
orgname[0] = shortname[0] = 0;
isOverlayDir = isDir = false;
id = MAX_OPENDIRS;
nextEntry = shortNr = 0;
CFileInfo(void)
: orgname{0},
shortname{0},
isOverlayDir(false),
isDir(false),
id(MAX_OPENDIRS),
nextEntry(0),
shortNr(0),
fileList(0),
longNameList(0)
{
}
~CFileInfo(void) {
for (Bit32u i=0; i<fileList.size(); i++) delete fileList[i];
@ -196,11 +204,13 @@ public:
};
private:
DOS_Drive_Cache(const DOS_Drive_Cache&); // prevent copying
DOS_Drive_Cache& operator= (const DOS_Drive_Cache&); // prevent assignment
void ClearFileInfo(CFileInfo *dir);
void DeleteFileInfo(CFileInfo *dir);
bool RemoveTrailingDot (char* shortname);
Bits GetLongName (CFileInfo* info, char* shortname);
Bits GetLongName (CFileInfo* info, char* shortname, const size_t shortname_len);
void CreateShortName (CFileInfo* dir, CFileInfo* info);
Bitu CreateShortNameID (CFileInfo* dir, const char* name);
int CompareShortname (const char* compareName, const char* shortName);

View file

@ -21,9 +21,10 @@
#define DOSBOX_SUPPORT_H
#include <algorithm>
#include <cstdio>
#include <ctype.h>
#include <string.h>
#include <string>
#include <ctype.h>
#ifndef DOSBOX_DOSBOX_H
#include "dosbox.h"
#endif
@ -33,6 +34,27 @@
#define strncasecmp(a,b,n) _strnicmp(a,b,n)
#endif
/// Copy a string into C array
///
/// This function copies string pointed by src to fixed-size buffer dst.
/// At most N bytes from src are copied, where N is size of dst.
/// If exactly N bytes are copied, then terminating null byte is put
/// into buffer, thus buffer overrun is prevented.
///
/// Function returns pointer to buffer to be compatible with std::strcpy.
///
/// Usage:
///
/// char buffer[2];
/// safe_strcpy(buffer, "abc");
/// // buffer is filled with "a"
template<size_t N>
char * safe_strcpy(char (& dst)[N], const char * src) noexcept {
snprintf(dst, N, "%s", src);
return & dst[0];
}
#define safe_strncpy(a,b,n) do { strncpy((a),(b),(n)-1); (a)[(n)-1] = 0; } while (0)
#ifdef HAVE_STRINGS_H

View file

@ -22,7 +22,8 @@
#include "support.h"
#include "cross.h"
// STL stuff
// System includes
#include <assert.h>
#include <vector>
#include <iterator>
#include <algorithm>
@ -60,45 +61,62 @@ bool SortByDirNameRev(DOS_Drive_Cache::CFileInfo* const &a, DOS_Drive_Cache::CFi
return strcmp(a->shortname,b->shortname)>0;
}
DOS_Drive_Cache::DOS_Drive_Cache(void) {
dirBase = new CFileInfo;
save_dir = 0;
srchNr = 0;
label[0] = 0;
nextFreeFindFirst = 0;
for (Bit32u i=0; i<MAX_OPENDIRS; i++) { dirSearch[i] = 0; dirFindFirst[i] = 0; };
SetDirSort(DIRALPHABETICAL);
updatelabel = true;
DOS_Drive_Cache::DOS_Drive_Cache(void)
: dirBase(new CFileInfo),
dirPath{0},
basePath{0},
sortDirType(DIRALPHABETICAL),
save_dir(nullptr),
save_path{0},
save_expanded{0},
srchNr(0),
dirSearch{nullptr},
dirFindFirst{nullptr},
nextFreeFindFirst(0),
label{0},
updatelabel(true)
{
}
DOS_Drive_Cache::DOS_Drive_Cache(const char* path) {
dirBase = new CFileInfo;
save_dir = 0;
srchNr = 0;
label[0] = 0;
nextFreeFindFirst = 0;
for (Bit32u i=0; i<MAX_OPENDIRS; i++) { dirSearch[i] = 0; dirFindFirst[i] = 0; };
SetDirSort(DIRALPHABETICAL);
DOS_Drive_Cache::DOS_Drive_Cache(const char* path)
: dirBase(new CFileInfo),
dirPath{0},
basePath{0},
sortDirType(DIRALPHABETICAL),
save_dir(nullptr),
save_path{0},
save_expanded{0},
srchNr(0),
dirSearch{nullptr},
dirFindFirst{nullptr},
nextFreeFindFirst(0),
label{0},
updatelabel(true)
{
SetBaseDir(path);
updatelabel = true;
}
DOS_Drive_Cache::~DOS_Drive_Cache(void) {
Clear();
for (Bit32u i=0; i<MAX_OPENDIRS; i++) { DeleteFileInfo(dirFindFirst[i]); dirFindFirst[i]=0; };
for (Bit32u i=0; i<MAX_OPENDIRS; i++) {
DeleteFileInfo(dirFindFirst[i]);
dirFindFirst[i] = nullptr;
}
}
void DOS_Drive_Cache::Clear(void) {
DeleteFileInfo(dirBase); dirBase = 0;
DeleteFileInfo(dirBase);
dirBase = nullptr;
nextFreeFindFirst = 0;
for (Bit32u i=0; i<MAX_OPENDIRS; i++) dirSearch[i] = 0;
for (Bit32u i=0; i<MAX_OPENDIRS; i++)
dirSearch[i] = nullptr;
}
void DOS_Drive_Cache::EmptyCache(void) {
// Empty Cache and reinit
Clear();
dirBase = new CFileInfo;
save_dir = 0;
save_dir = nullptr;
srchNr = 0;
SetBaseDir(basePath);
}
@ -124,13 +142,18 @@ Bit16u DOS_Drive_Cache::GetFreeID(CFileInfo* dir) {
}
}
LOG(LOG_FILES,LOG_NORMAL)("DIRCACHE: Too many open directories!");
dir->id=0;
dir->id = 0;
return 0;
}
void DOS_Drive_Cache::SetBaseDir(const char* baseDir) {
// Guard if source and destination are the same
if (basePath == baseDir) {
return;
}
safe_strcpy(basePath, baseDir);
Bit16u id;
strcpy(basePath,baseDir);
if (OpenDir(baseDir,id)) {
char* result = 0;
ReadDir(id,result);
@ -162,15 +185,15 @@ void DOS_Drive_Cache::SetBaseDir(const char* baseDir) {
}
void DOS_Drive_Cache::ExpandName(char* path) {
strcpy(path,GetExpandName(path));
safe_strncpy(path, GetExpandName(path), CROSS_LEN);
}
char* DOS_Drive_Cache::GetExpandName(const char* path) {
static char work [CROSS_LEN] = { 0 };
char dir [CROSS_LEN];
char dir [CROSS_LEN];
work[0] = 0;
strcpy (dir,path);
safe_strcpy (dir, path);
const char* pos = strrchr(path,CROSS_FILESPLIT);
@ -179,9 +202,9 @@ char* DOS_Drive_Cache::GetExpandName(const char* path) {
if (pos) {
// Last Entry = File
strcpy(dir,pos+1);
GetLongName(dirInfo, dir);
strcat(work,dir);
safe_strcpy(dir, pos+1);
(void) GetLongName(dirInfo, dir, sizeof(dir)); // ignore the return code
strncat(work, dir, sizeof(work) - strlen(work) - 1);
}
if (*work) {
@ -206,20 +229,20 @@ void DOS_Drive_Cache::AddEntry(const char* path, bool checkExists) {
CFileInfo* dir = FindDirInfo(path,expand);
const char* pos = strrchr(path,CROSS_FILESPLIT);
if (pos) {
strcpy(file,pos+1);
if (pos && dir) {
safe_strcpy(file, pos+1);
// Check if file already exists, then don't add new entry...
if (checkExists) {
if (GetLongName(dir,file)>=0) return;
if (GetLongName(dir, file, sizeof(file))>=0) return;
}
CreateEntry(dir,file,false);
Bits index = GetLongName(dir,file);
Bits index = GetLongName(dir, file, sizeof(file));
if (index>=0) {
Bit32u i;
// Check if there are any open search dir that are affected by this...
if (dir) for (i=0; i<MAX_OPENDIRS; i++) {
for (i=0; i<MAX_OPENDIRS; i++) {
if ((dirSearch[i]==dir) && ((Bit32u)index<=dirSearch[i]->nextEntry))
dirSearch[i]->nextEntry++;
}
@ -236,7 +259,7 @@ void DOS_Drive_Cache::AddEntryDirOverlay(const char* path, bool checkExists) {
char dironly[CROSS_LEN + 1];
//When adding a directory, the directory we want to operate inside in is the above it. (which can go wrong if the directory already exists.)
strcpy(dironly,path);
safe_strcpy(dironly, path);
char* post = strrchr(dironly,CROSS_FILESPLIT);
if (post) {
@ -255,11 +278,11 @@ void DOS_Drive_Cache::AddEntryDirOverlay(const char* path, bool checkExists) {
CFileInfo* dir = FindDirInfo(dironly,expand);
const char* pos = strrchr(path,CROSS_FILESPLIT);
if (pos) {
strcpy(file,pos + 1);
if (pos && dir) {
safe_strcpy(file, pos + 1);
// Check if directory already exists, then don't add new entry...
if (checkExists) {
Bits index = GetLongName(dir,file);
Bits index = GetLongName(dir, file, sizeof(file));
if (index >= 0) {
//directory already exists, but most likely empty.
dir = dir->fileList[index];
@ -276,11 +299,11 @@ void DOS_Drive_Cache::AddEntryDirOverlay(const char* path, bool checkExists) {
CreateEntry(dir,file,true);
Bits index = GetLongName(dir,file);
Bits index = GetLongName(dir, file, sizeof(file));
if (index>=0) {
Bit32u i;
// Check if there are any open search dir that are affected by this...
if (dir) for (i=0; i<MAX_OPENDIRS; i++) {
for (i=0; i<MAX_OPENDIRS; i++) {
if ((dirSearch[i]==dir) && ((Bit32u)index<=dirSearch[i]->nextEntry))
dirSearch[i]->nextEntry++;
}
@ -320,11 +343,12 @@ void DOS_Drive_Cache::CacheOut(const char* path, bool ignoreLastDir) {
char tmp[CROSS_LEN] = { 0 };
Bit32s len=0;
const char* pos = strrchr(path,CROSS_FILESPLIT);
if (pos) len = (Bit32s)(pos - path);
if (len>0) {
safe_strncpy(tmp,path,len+1);
if (pos)
len = (Bit32s)(pos - path);
if (len>0) {
safe_strncpy(tmp,path,len+1);
} else {
strcpy(tmp,path);
safe_strcpy(tmp, path);
}
dir = FindDirInfo(tmp,expand);
} else {
@ -335,13 +359,15 @@ void DOS_Drive_Cache::CacheOut(const char* path, bool ignoreLastDir) {
// delete file objects...
//Maybe check if it is a file and then only delete the file and possibly the long name. instead of all objects in the dir.
for(Bit32u i=0; i<dir->fileList.size(); i++) {
if (dirSearch[srchNr]==dir->fileList[i]) dirSearch[srchNr] = 0;
DeleteFileInfo(dir->fileList[i]); dir->fileList[i] = 0;
if (dirSearch[srchNr]==dir->fileList[i])
dirSearch[srchNr] = nullptr;
DeleteFileInfo(dir->fileList[i]);
dir->fileList[i] = nullptr;
}
// clear lists
dir->fileList.clear();
dir->longNameList.clear();
save_dir = 0;
save_dir = nullptr;
}
bool DOS_Drive_Cache::IsCachedIn(CFileInfo* curDir) {
@ -355,10 +381,14 @@ bool DOS_Drive_Cache::GetShortName(const char* fullname, char* shortname) {
CFileInfo* curDir = FindDirInfo(fullname,expand);
const char* pos = strrchr(fullname,CROSS_FILESPLIT);
if (pos) pos++; else return false;
if (pos)
pos++;
else
return false;
std::vector<CFileInfo*>::size_type filelist_size = curDir->longNameList.size();
if (GCC_UNLIKELY(filelist_size<=0)) return false;
if (GCC_UNLIKELY(filelist_size<=0))
return false;
// The orgname part of the list is not sorted (shortname is)! So we can only walk through it.
for(Bitu i = 0; i < filelist_size; i++) {
@ -367,7 +397,7 @@ bool DOS_Drive_Cache::GetShortName(const char* fullname, char* shortname) {
#else
if (strcmp(pos,curDir->longNameList[i]->orgname) == 0) {
#endif
strcpy(shortname,curDir->longNameList[i]->shortname);
safe_strncpy(shortname, curDir->longNameList[i]->shortname, DOS_NAMELENGTH_ASCII);
return true;
}
}
@ -498,7 +528,7 @@ static Bits wine_hash_short_file_name( char* name, char* buffer )
}
#endif
Bits DOS_Drive_Cache::GetLongName(CFileInfo* curDir, char* shortName) {
Bits DOS_Drive_Cache::GetLongName(CFileInfo* curDir, char* shortName, const size_t shortName_len) {
std::vector<CFileInfo*>::size_type filelist_size = curDir->fileList.size();
if (GCC_UNLIKELY(filelist_size<=0)) return -1;
@ -514,7 +544,7 @@ Bits DOS_Drive_Cache::GetLongName(CFileInfo* curDir, char* shortName) {
if (res>0) low = mid+1; else
if (res<0) high = mid-1; else
{ // Found
strcpy(shortName,curDir->fileList[mid]->orgname);
safe_strncpy(shortName, curDir->fileList[mid]->orgname, shortName_len);
return mid;
};
}
@ -528,7 +558,7 @@ Bits DOS_Drive_Cache::GetLongName(CFileInfo* curDir, char* shortName) {
buff[res] = 0;
if (!strcmp(shortName,buff)) {
// Found
strcpy(shortName,curDir->fileList[i]->orgname);
safe_strncpy(shortName, curDir->fileList[i]->orgname, shortName_len);
return (Bits)i;
}
}
@ -557,7 +587,9 @@ void DOS_Drive_Cache::CreateShortName(CFileInfo* curDir, CFileInfo* info) {
char* tmpName = tmpNameBuffer;
// Remove Spaces
strcpy(tmpName,info->orgname);
// avoid using safe_strncpy to prevent GCC warning about truncation on an incomplete copy
strncpy(tmpName, info->orgname, CROSS_LEN);
tmpName[CROSS_LEN - 1] = '\0'; // zero-terminate even if the source wasn't
upcase(tmpName);
createShort = RemoveSpaces(tmpName);
@ -565,45 +597,52 @@ void DOS_Drive_Cache::CreateShortName(CFileInfo* curDir, CFileInfo* info) {
char* pos = strchr(tmpName,'.');
if (pos) {
// ignore preceding '.' if extension is longer than "3"
if (strlen(pos)>4) {
if (strlen(pos) > 4) {
while (*tmpName=='.') tmpName++;
createShort = true;
}
pos = strchr(tmpName,'.');
if (pos) len = (Bits)(pos - tmpName);
else len = (Bits)strlen(tmpName);
if (pos)
len = pos - tmpName;
else
len = (Bits)strlen(tmpName);
} else {
len = (Bits)strlen(tmpName);
len = strlen(tmpName);
}
// Should shortname version be created ?
createShort = createShort || (len>8);
if (!createShort) {
char buffer[CROSS_LEN];
strcpy(buffer,tmpName);
createShort = (GetLongName(curDir,buffer)>=0);
safe_strcpy(buffer, tmpName);
createShort = (GetLongName(curDir, buffer, sizeof(buffer)) >= 0);
}
if (createShort) {
// Create number
char buffer[8];
info->shortNr = CreateShortNameID(curDir,tmpName);
sprintf(buffer,"%d",info->shortNr);
sprintf(buffer,"%" PRIuPTR, info->shortNr);
// Copy first letters
Bits tocopy = 0;
size_t buflen = strlen(buffer);
if (len+buflen+1>8) tocopy = (Bits)(8 - buflen - 1);
else tocopy = len;
safe_strncpy(info->shortname,tmpName,tocopy+1);
if (len + buflen + 1 > 8)
tocopy = (Bits)(8 - buflen - 1);
else
tocopy = len;
// Copy the lesser of "DOS_NAMELENGTH_ASCII" or "tocopy + 1" characters.
safe_strncpy(info->shortname, tmpName,
tocopy < DOS_NAMELENGTH_ASCII ? tocopy + 1 : DOS_NAMELENGTH_ASCII);
// Copy number
strcat(info->shortname,"~");
strcat(info->shortname,buffer);
strncat(info->shortname, "~", DOS_NAMELENGTH_ASCII - strlen(info->shortname) - 1);
strncat(info->shortname, buffer, DOS_NAMELENGTH_ASCII - strlen(info->shortname) - 1);
// Add (and cut) Extension, if available
if (pos) {
// Step to last extension...
pos = strrchr(tmpName, '.');
pos = strrchr(tmpName, '.'); // extensions are at-most 3 chars (4 with terminator)
// add extension
strncat(info->shortname,pos,4);
unsigned int remaining_space = DOS_NAMELENGTH_ASCII - strlen(info->shortname) - 1;
strncat(info->shortname, pos, 4 < remaining_space ? 4 : remaining_space);
info->shortname[DOS_NAMELENGTH] = 0;
}
@ -631,7 +670,7 @@ void DOS_Drive_Cache::CreateShortName(CFileInfo* curDir, CFileInfo* info) {
curDir->longNameList.push_back(info);
}
} else {
strcpy(info->shortname,tmpName);
safe_strncpy(info->shortname, tmpName, DOS_NAMELENGTH_ASCII);
}
RemoveTrailingDot(info->shortname);
}
@ -648,7 +687,7 @@ DOS_Drive_Cache::CFileInfo* DOS_Drive_Cache::FindDirInfo(const char* path, char*
Bit16u id;
if (save_dir && (strcmp(path,save_path)==0)) {
strcpy(expandedPath,save_expanded);
safe_strncpy(expandedPath, save_expanded, CROSS_LEN);
return save_dir;
};
@ -656,33 +695,37 @@ DOS_Drive_Cache::CFileInfo* DOS_Drive_Cache::FindDirInfo(const char* path, char*
// Remove base dir path
start += strlen(basePath);
strcpy(expandedPath,basePath);
safe_strncpy(expandedPath, basePath, CROSS_LEN);
// hehe, baseDir should be cached in...
if (!IsCachedIn(curDir)) {
strcpy(work,basePath);
safe_strcpy(work, basePath);
if (OpenDir(curDir,work,id)) {
char buffer[CROSS_LEN];
char* result = 0;
strcpy(buffer,dirPath);
safe_strcpy(buffer, dirPath);
ReadDir(id,result);
strcpy(dirPath,buffer);
safe_strcpy(dirPath, buffer);
if (dirSearch[id]) {
dirSearch[id]->id = MAX_OPENDIRS;
dirSearch[id] = 0;
dirSearch[id] = nullptr;
}
};
};
do {
// bool errorcheck = false;
pos = strchr(start,CROSS_FILESPLIT);
if (pos) { safe_strncpy(dir,start,pos-start+1); /*errorcheck = true;*/ }
else { strcpy(dir,start); };
if (pos) {
safe_strncpy(dir, start,
static_cast<unsigned int>(pos - start) < sizeof(dir) ? pos - start + 1 : sizeof(dir));
}
else {
safe_strcpy(dir, start);
};
// Path found
Bits nextDir = GetLongName(curDir,dir);
strcat(expandedPath,dir);
Bits nextDir = GetLongName(curDir, dir, sizeof(dir));
strncat(expandedPath, dir, CROSS_LEN - strlen(expandedPath) - 1);
// Error check
/* if ((errorcheck) && (nextDir<0)) {
@ -692,30 +735,30 @@ DOS_Drive_Cache::CFileInfo* DOS_Drive_Cache::FindDirInfo(const char* path, char*
// Follow Directory
if ((nextDir>=0) && curDir->fileList[nextDir]->isDir) {
curDir = curDir->fileList[nextDir];
strcpy (curDir->orgname,dir);
safe_strcpy(curDir->orgname, dir);
if (!IsCachedIn(curDir)) {
if (OpenDir(curDir,expandedPath,id)) {
char buffer[CROSS_LEN];
char* result = 0;
strcpy(buffer,dirPath);
safe_strcpy(buffer, dirPath);
ReadDir(id,result);
strcpy(dirPath,buffer);
safe_strcpy(dirPath, buffer);
if (dirSearch[id]) {
dirSearch[id]->id = MAX_OPENDIRS;
dirSearch[id] = 0;
dirSearch[id] = nullptr;
}
};
}
};
if (pos) {
strcat(expandedPath,split);
strncat(expandedPath, split, CROSS_LEN - strlen(expandedPath) - 1);
start = pos+1;
}
} while (pos);
// Save last result for faster access next time
strcpy(save_path,path);
strcpy(save_expanded,expandedPath);
safe_strcpy(save_path, path);
safe_strcpy(save_expanded, expandedPath);
save_dir = curDir;
return curDir;
@ -735,10 +778,12 @@ bool DOS_Drive_Cache::OpenDir(CFileInfo* dir, const char* expand, Bit16u& id) {
id = GetFreeID(dir);
dirSearch[id] = dir;
char expandcopy [CROSS_LEN];
strcpy(expandcopy,expand);
safe_strcpy(expandcopy, expand);
// Add "/"
char end[2]={CROSS_FILESPLIT,0};
if (expandcopy[strlen(expandcopy)-1]!=CROSS_FILESPLIT) strcat(expandcopy,end);
if (expandcopy[strlen(expandcopy)-1] != CROSS_FILESPLIT) {
strncat(expandcopy, end, sizeof(expandcopy) - strlen(expandcopy) - 1);
}
// open dir
if (dirSearch[id]) {
// open dir
@ -746,12 +791,12 @@ bool DOS_Drive_Cache::OpenDir(CFileInfo* dir, const char* expand, Bit16u& id) {
if (dirp || dir->isOverlayDir) {
// Reset it..
if (dirp) close_directory(dirp);
strcpy(dirPath,expandcopy);
safe_strcpy(dirPath, expandcopy);
return true;
}
if (dirSearch[id]) {
dirSearch[id]->id = MAX_OPENDIRS;
dirSearch[id] = 0;
dirSearch[id] = nullptr;
}
};
return false;
@ -759,7 +804,7 @@ bool DOS_Drive_Cache::OpenDir(CFileInfo* dir, const char* expand, Bit16u& id) {
void DOS_Drive_Cache::CreateEntry(CFileInfo* dir, const char* name, bool is_directory) {
CFileInfo* info = new CFileInfo;
strcpy(info->orgname, name);
safe_strcpy(info->orgname, name);
info->shortNr = 0;
info->isDir = is_directory;
@ -795,8 +840,8 @@ void DOS_Drive_Cache::CreateEntry(CFileInfo* dir, const char* name, bool is_dire
void DOS_Drive_Cache::CopyEntry(CFileInfo* dir, CFileInfo* from) {
CFileInfo* info = new CFileInfo;
// just copy things into new fileinfo
strcpy(info->orgname, from->orgname);
strcpy(info->shortname, from->shortname);
safe_strcpy(info->orgname, from->orgname);
safe_strcpy(info->shortname, from->shortname);
info->shortNr = from->shortNr;
info->isDir = from->isDir;
@ -805,7 +850,8 @@ void DOS_Drive_Cache::CopyEntry(CFileInfo* dir, CFileInfo* from) {
bool DOS_Drive_Cache::ReadDir(Bit16u id, char* &result) {
// shouldnt happen...
if (id>MAX_OPENDIRS) return false;
if (id >= MAX_OPENDIRS)
return false;
if (!IsCachedIn(dirSearch[id])) {
// Try to open directory
@ -813,7 +859,7 @@ bool DOS_Drive_Cache::ReadDir(Bit16u id, char* &result) {
if (!dirp) {
if (dirSearch[id]) {
dirSearch[id]->id = MAX_OPENDIRS;
dirSearch[id] = 0;
dirSearch[id] = nullptr;
}
return false;
}
@ -843,7 +889,7 @@ bool DOS_Drive_Cache::ReadDir(Bit16u id, char* &result) {
if (SetResult(dirSearch[id], result, dirSearch[id]->nextEntry)) return true;
if (dirSearch[id]) {
dirSearch[id]->id = MAX_OPENDIRS;
dirSearch[id] = 0;
dirSearch[id] = nullptr;
}
return false;
}
@ -856,7 +902,7 @@ bool DOS_Drive_Cache::SetResult(CFileInfo* dir, char* &result, Bitu entryNr)
if (entryNr>=dir->fileList.size()) return false;
CFileInfo* info = dir->fileList[entryNr];
// copy filename, short version
strcpy(res,info->shortname);
safe_strcpy(res, info->shortname);
// Set to next Entry
dir->nextEntry = entryNr+1;
return true;
@ -872,7 +918,7 @@ bool DOS_Drive_Cache::FindFirst(char* path, Bit16u& id) {
//If the next one isn't free, move on to the next, if none is free => reset and assume the worst
Bit16u local_findcounter = 0;
while ( local_findcounter < MAX_OPENDIRS ) {
if (dirFindFirst[this->nextFreeFindFirst] == 0) break;
if (dirFindFirst[this->nextFreeFindFirst] == nullptr) break;
if (++this->nextFreeFindFirst >= MAX_OPENDIRS) this->nextFreeFindFirst = 0; //Wrap around
local_findcounter++;
}
@ -889,12 +935,13 @@ bool DOS_Drive_Cache::FindFirst(char* path, Bit16u& id) {
for(Bitu n=0; n<MAX_OPENDIRS;n++) {
// Clear and reuse slot
DeleteFileInfo(dirFindFirst[n]);
dirFindFirst[n]=0;
dirFindFirst[n] = nullptr;
}
}
}
assert(dirFindFirst[dirFindFirstID] == nullptr);
dirFindFirst[dirFindFirstID] = new CFileInfo();
dirFindFirst[dirFindFirstID]-> nextEntry = 0;
dirFindFirst[dirFindFirstID]-> nextEntry = 0;
// Copy entries to use with FindNext
for (Bitu i=0; i<dirSearch[dirID]->fileList.size(); i++) {
@ -923,7 +970,8 @@ bool DOS_Drive_Cache::FindNext(Bit16u id, char* &result) {
}
if (!SetResult(dirFindFirst[id], result, dirFindFirst[id]->nextEntry)) {
// free slot
DeleteFileInfo(dirFindFirst[id]); dirFindFirst[id] = 0;
DeleteFileInfo(dirFindFirst[id]);
dirFindFirst[id] = nullptr;
return false;
}
return true;
@ -935,13 +983,14 @@ void DOS_Drive_Cache::ClearFileInfo(CFileInfo *dir) {
ClearFileInfo(info);
}
if (dir->id != MAX_OPENDIRS) {
dirSearch[dir->id] = 0;
dirSearch[dir->id] = nullptr;
dir->id = MAX_OPENDIRS;
}
}
void DOS_Drive_Cache::DeleteFileInfo(CFileInfo *dir) {
if (dir)
if (dir) {
ClearFileInfo(dir);
delete dir;
delete dir;
}
}

View file

@ -185,6 +185,8 @@ public:
imageDisk *loadedDisk;
bool created_successfully;
private:
fatDrive(const fatDrive&); // prevent copying
fatDrive& operator= (const fatDrive&); // prevent assignment
Bit32u getClusterValue(Bit32u clustNum);
void setClusterValue(Bit32u clustNum, Bit32u clustValue);
Bit32u getClustFirstSect(Bit32u clustNum);
@ -408,6 +410,8 @@ public:
virtual Bits UnMount(void);
virtual char const* GetLabel(void);
private:
Virtual_Drive(const Virtual_Drive&); // prevent copying
Virtual_Drive& operator= (const Virtual_Drive&); // prevent assignment
VFILE_Block * search_file;
};