fix vfat (broken in r5438). file sizes weren't counted right. only ~36MB would get allocated and then it would get blown when loading the files.

This commit is contained in:
zeromus 2016-11-11 02:33:33 +00:00
parent 6e0077ecb9
commit 2801ee5d19
1 changed files with 67 additions and 38 deletions

View File

@ -43,6 +43,9 @@ enum EListCallbackArg {
typedef void (*ListCallback)(RDIR* rdir, EListCallbackArg); typedef void (*ListCallback)(RDIR* rdir, EListCallbackArg);
// List all files and subdirectories recursively // List all files and subdirectories recursively
//TODO: clunky architecture. we've combined the callbacks into one handler.
//we could merge the callback and list_files function, or refactor the callback into one for each enum which receives a unit of work after
//the more detailed recursing logic (caused by libretro-common integration) is handled in the lister
static void list_files(const char *filepath, ListCallback list_callback) static void list_files(const char *filepath, ListCallback list_callback)
{ {
void * hFind; void * hFind;
@ -64,6 +67,7 @@ static void list_files(const char *filepath, ListCallback list_callback)
const char* fname = retro_dirent_get_name(rdir); const char* fname = retro_dirent_get_name(rdir);
list_callback(rdir,EListCallbackArg_Item); list_callback(rdir,EListCallbackArg_Item);
printf("cflash added %s\n",fname);
if(retro_dirent_is_dir(rdir) && (strcmp(fname, ".")) && (strcmp(fname, ".."))) if(retro_dirent_is_dir(rdir) && (strcmp(fname, ".")) && (strcmp(fname, "..")))
{ {
@ -76,28 +80,24 @@ static void list_files(const char *filepath, ListCallback list_callback)
retro_closedir(rdir); retro_closedir(rdir);
} }
static u64 dataSectors = 0; enum eCallbackType
void count_ListCallback(RDIR* rdir, EListCallbackArg arg)
{ {
if(arg == EListCallbackArg_Pop) return; eCallbackType_Count, eCallbackType_Build
u32 sectors = 1; };
if(retro_dirent_is_dir(rdir))
{
}
else
{
//allocate sectors for file
int32_t fileSize = path_get_size(retro_dirent_get_name(rdir));
sectors += (fileSize+511)/512 + 1;
}
dataSectors += sectors;
}
static eCallbackType callbackType;
//for eCallbackType_Count:
static bool count_failed = false;
static u64 dataSectors = 0;
//recursing related.. really ought to be merged with list_files functionality
static std::string currPath; static std::string currPath;
static std::stack<std::string> pathStack; static std::stack<std::string> pathStack;
static std::stack<std::string> virtPathStack; static std::stack<std::string> virtPathStack;
static std::string currVirtPath; static std::string currVirtPath;
void build_ListCallback(RDIR* rdir, EListCallbackArg arg)
static void DirectoryListCallback(RDIR* rdir, EListCallbackArg arg)
{ {
const char* fname = retro_dirent_get_name(rdir); const char* fname = retro_dirent_get_name(rdir);
@ -119,10 +119,18 @@ void build_ListCallback(RDIR* rdir, EListCallbackArg arg)
virtPathStack.push(currVirtPath); virtPathStack.push(currVirtPath);
currVirtPath = currVirtPath + "/" + fname; currVirtPath = currVirtPath + "/" + fname;
bool ok = LIBFAT::MkDir(currVirtPath.c_str());
if(!ok) if(callbackType == eCallbackType_Build)
printf("ERROR adding dir %s via libfat\n",currVirtPath.c_str()); {
bool ok = LIBFAT::MkDir(currVirtPath.c_str());
if(!ok)
printf("ERROR adding dir %s via libfat\n",currVirtPath.c_str());
}
else
{
dataSectors++; //directories take one sector
}
currPath = currPath + path_default_slash() + fname; currPath = currPath + path_default_slash() + fname;
return; return;
@ -131,38 +139,56 @@ void build_ListCallback(RDIR* rdir, EListCallbackArg arg)
{ {
std::string path = currPath + path_default_slash() + fname; std::string path = currPath + path_default_slash() + fname;
FILE* inf = fopen(path.c_str(),"rb"); if(callbackType == eCallbackType_Build)
if(inf)
{ {
fseek(inf,0,SEEK_END); FILE* inf = fopen(path.c_str(),"rb");
long len = ftell(inf); if(inf)
fseek(inf,0,SEEK_SET); {
u8 *buf = new u8[len]; fseek(inf,0,SEEK_END);
fread(buf,1,len,inf); long len = ftell(inf);
fclose(inf); fseek(inf,0,SEEK_SET);
u8 *buf = new u8[len];
fread(buf,1,len,inf);
fclose(inf);
std::string path = currVirtPath + "/" + fname; std::string path = currVirtPath + "/" + fname;
printf("FAT + (%10.2f KB) %s \n",len/1024.f,path.c_str()); printf("FAT + (%10.2f KB) %s \n",len/1024.f,path.c_str());
bool ok = LIBFAT::WriteFile(path.c_str(),buf,len); bool ok = LIBFAT::WriteFile(path.c_str(),buf,len);
if(!ok) if(!ok)
printf("ERROR adding file to fat\n"); printf("ERROR adding file to fat\n");
delete[] buf; delete[] buf;
} else printf("ERROR opening file for fat\n"); } else printf("ERROR opening file for fat\n");
}
else
{
//allocate sectors for file
int32_t fileSize = path_get_size(path.c_str());
if(fileSize == -1) { count_failed = true; dataSectors = 0; }
else dataSectors += (fileSize+511)/512 + 1;
}
} }
} }
bool VFAT::build(const char* path, int extra_MB) bool VFAT::build(const char* path, int extra_MB)
{ {
dataSectors = 0; dataSectors = 0;
currVirtPath = ""; currVirtPath = "";
currPath = path; currPath = path;
list_files(path, count_ListCallback);
count_failed = false;
callbackType = eCallbackType_Count;
list_files(path, DirectoryListCallback);
if(count_failed)
{
printf("FAILED enumerating files for fat\n");
return false;
}
dataSectors += 8; //a few for reserved sectors, etc. dataSectors += 8; //a few for reserved sectors, etc.
dataSectors += extra_MB*1024*1024/512; //add extra write space dataSectors += extra_MB*1024*1024/512; //add extra write space
//dataSectors += 16*1024*1024/512; //add 16MB worth of write space. this is probably enough for anyone, but maybe it should be configurable. //dataSectors += 16*1024*1024/512; //add 16MB worth of write space. this is probably enough for anyone, but maybe it should be configurable.
//we could always suggest to users to add a big file to their directory to overwrite (that would cause the image to get padded) //we could always suggest to users to add a big file to their directory to overwrite (that would cause the image to get padded)
@ -171,6 +197,8 @@ bool VFAT::build(const char* path, int extra_MB)
if(dataSectors<36*1024*1024/512) if(dataSectors<36*1024*1024/512)
dataSectors = 36*1024*1024/512; dataSectors = 36*1024*1024/512;
printf("dataSectors: %lld\n",dataSectors);
if(dataSectors>=(0x80000000>>9)) if(dataSectors>=(0x80000000>>9))
{ {
printf("error allocating memory for fat (%d KBytes)\n",(dataSectors*512)/1024); printf("error allocating memory for fat (%d KBytes)\n",(dataSectors*512)/1024);
@ -207,7 +235,8 @@ bool VFAT::build(const char* path, int extra_MB)
//setup libfat and write all the files through it //setup libfat and write all the files through it
LIBFAT::Init(memf->buf(),memf->size()); LIBFAT::Init(memf->buf(),memf->size());
list_files(path, build_ListCallback); callbackType = eCallbackType_Build;
list_files(path, DirectoryListCallback);
LIBFAT::Shutdown(); LIBFAT::Shutdown();
return true; return true;