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:
parent
88cdd8d3a0
commit
cff6b05559
4 changed files with 200 additions and 115 deletions
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue