From b4b8138150ff2e67b1416551f5cefceb760c5e3d Mon Sep 17 00:00:00 2001 From: Maschell Date: Sun, 8 Dec 2019 22:49:08 +0100 Subject: [PATCH] Use romfs from wut, clean up, add support for custom icon in hbm --- src/main.cpp | 493 +++----------------------- src/readFileWrapper.cpp | 244 +++++++++++++ src/readFileWrapper.h | 37 ++ src/romfs_dev.c | 702 -------------------------------------- src/romfs_dev.h | 90 ----- src/romfs_helper.cpp | 88 +++++ src/romfs_helper.h | 26 ++ src/utils/StringTools.cpp | 79 +++++ src/utils/StringTools.h | 34 +- 9 files changed, 526 insertions(+), 1267 deletions(-) create mode 100644 src/readFileWrapper.cpp create mode 100644 src/readFileWrapper.h delete mode 100644 src/romfs_dev.c delete mode 100644 src/romfs_dev.h create mode 100644 src/romfs_helper.cpp create mode 100644 src/romfs_helper.h diff --git a/src/main.cpp b/src/main.cpp index e07a6a7..07ad9e7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,11 +23,12 @@ #include #include #include +#include "utils/StringTools.h" #include -#include "romfs_dev.h" +#include #include "filelist.h" - - +#include "readFileWrapper.h" +#include "romfs_helper.h" WUPS_PLUGIN_NAME("Homebrew SysLauncher"); WUPS_PLUGIN_DESCRIPTION("Allows the user to load homebrew from the System Menu"); @@ -35,33 +36,12 @@ WUPS_PLUGIN_VERSION("0.1"); WUPS_PLUGIN_AUTHOR("Maschell"); WUPS_PLUGIN_LICENSE("GPL"); -typedef struct WUT_PACKED FileInfos_ { - char path[256]; - char name[256]; - int32_t source; - bool romfsMounted; - int openedFiles; -} FileInfos; - -typedef struct{ - bool inUse; - int fd; - bool compressed; - bool cInitDone; - bool cCloseDone; - z_stream strm; - unsigned char in[0x1000]; -} fileReadInformation; - -#define FILE_INFO_SIZE 300 -FileInfos gFileInfos[FILE_INFO_SIZE] __attribute__((section(".data"))); -fileReadInformation gFileReadInformation[32] __attribute__((section(".data"))); +char gIconCache[65580] __attribute__((section(".data"))); ACPMetaXml gLaunchXML __attribute__((section(".data"))); MCPTitleListType template_title __attribute__((section(".data"))); BOOL gHomebrewLaunched __attribute__((section(".data"))); - WUPS_USE_WUT_CRT() INITIALIZE_PLUGIN() { @@ -69,88 +49,10 @@ INITIALIZE_PLUGIN() { memset((void*) &gLaunchXML,0,sizeof(gLaunchXML)); memset((void*) &gFileInfos,0,sizeof(gFileInfos)); memset((void*) &gFileReadInformation,0,sizeof(gFileReadInformation)); + memset((void*) &gIconCache,0,sizeof(gIconCache)); gHomebrewLaunched = FALSE; } -int EndsWith(const char *str, const char *suffix); - -void closeAllStreams() { - for(int i = 0; i<32; i++) { - if(gFileReadInformation[i].inUse != false) { - - } - } -} - -int fileReadInformation_getSlot() { - for(int i = 0; i<32; i++) { - if(gFileReadInformation[i].inUse == false) { - gFileReadInformation[i].inUse = true; - return i; - } - } - return -1; -} - -void unmountRomfs(uint32_t id); - -int EndsWith(const char *str, const char *suffix) { - if (!str || !suffix) - return 0; - size_t lenstr = strlen(str); - size_t lensuffix = strlen(suffix); - if (lensuffix > lenstr) - return 0; - return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0; -} - -bool mountRomfs(uint32_t id) { - if(id >= FILE_INFO_SIZE){ - DEBUG_FUNCTION_LINE("HANDLE WAS TOO BIG\n"); - return false; - } - if(!gFileInfos[id].romfsMounted) { - char buffer [256]; - snprintf(buffer,256,"fs:/vol/external01/%s", gFileInfos[id].path); - char romName [10]; - snprintf(romName,10,"%08X", id); - DEBUG_FUNCTION_LINE("Mount %s as %s\n", buffer, romName); - if(romfsMount(romName,buffer) == 0) { - DEBUG_FUNCTION_LINE("Mounted successfully \n"); - gFileInfos[id].romfsMounted = true; - return true; - } else { - DEBUG_FUNCTION_LINE("Mounting failed\n"); - return false; - } - } - return true; -} - - - -void listdir(const char *name, int indent) { - DEBUG_FUNCTION_LINE("Reading %s\n",name); - DIR *dir; - struct dirent *entry; - - if (!(dir = opendir(name))) - return; - - while ((entry = readdir(dir)) != NULL) { - if (entry->d_type == DT_DIR) { - char path[1024]; - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - snprintf(path, sizeof(path), "%s%s", name, entry->d_name); - DEBUG_FUNCTION_LINE("%*s[%s]\n", indent, "", entry->d_name); - listdir(path, indent + 2); - } else { - DEBUG_FUNCTION_LINE("%*s- %s\n", indent, "", entry->d_name); - } - } - closedir(dir); -} ON_APPLICATION_START(args) { socket_lib_init(); @@ -163,14 +65,13 @@ ON_APPLICATION_START(args) { } } -void unmountAllRomfs(); ON_APPLICATION_END() { - closeAllStreams(); + DeInitAllFiles(); unmountAllRomfs(); } void fillXmlForTitleID(uint32_t titleid_upper, uint32_t titleid_lower, ACPMetaXml* out_buf) { - if(titleid_lower >= FILE_INFO_SIZE){ + if(titleid_lower >= FILE_INFO_SIZE) { return; } out_buf->title_id = ((uint64_t)titleid_upper * 0x100000000) + titleid_lower; @@ -197,53 +98,6 @@ void fillXmlForTitleID(uint32_t titleid_upper, uint32_t titleid_lower, ACPMetaXm strncpy(out_buf->company_code,"0001",strlen("0001")); } -// You must free the result if result is non-NULL. -char *str_replace(char *orig, char *rep, char *with) { - char *result; // the return string - char *ins; // the next insert point - char *tmp; // varies - int len_rep; // length of rep (the string to remove) - int len_with; // length of with (the string to replace rep with) - int len_front; // distance between rep and end of last rep - int count; // number of replacements - - // sanity checks and initialization - if (!orig || !rep) - return NULL; - len_rep = strlen(rep); - if (len_rep == 0) - return NULL; // empty rep causes infinite loop during count - if (!with) - with = ""; - len_with = strlen(with); - - // count the number of replacements needed - ins = orig; - for (count = 0; tmp = strstr(ins, rep); ++count) { - ins = tmp + len_rep; - } - - tmp = result = (char*)malloc(strlen(orig) + (len_with - len_rep) * count + 1); - - if (!result) - return NULL; - - // first time through the loop, all the variable are set correctly - // from here on, - // tmp points to the end of the result string - // ins points to the next occurrence of rep in orig - // orig points to the remainder of orig after "end of rep" - while (count--) { - ins = strstr(orig, rep); - len_front = ins - orig; - tmp = strncpy(tmp, orig, len_front) + len_front; - tmp = strcpy(tmp, with) + len_with; - orig += len_front + len_rep; // move to next "end of rep" - } - strcpy(tmp, orig); - return result; -} - DECL_FUNCTION(int32_t, MCP_TitleList, uint32_t handle, uint32_t* outTitleCount, MCPTitleListType* titleList, uint32_t size) { int32_t result = real_MCP_TitleList(handle, outTitleCount, titleList, size); uint32_t titlecount = *outTitleCount; @@ -253,7 +107,7 @@ DECL_FUNCTION(int32_t, MCP_TitleList, uint32_t handle, uint32_t* outTitleCount, int j = 0; for(int i = 0; i < dirList.GetFilecount(); i++) { - if(j >= FILE_INFO_SIZE){ + if(j >= FILE_INFO_SIZE) { DEBUG_FUNCTION_LINE("TOO MANY TITLES\n"); break; } @@ -279,7 +133,7 @@ DECL_FUNCTION(int32_t, MCP_TitleList, uint32_t handle, uint32_t* outTitleCount, char * with = (char*)""; char * input = (char*) dirList.GetFilepath(i); - char * path = str_replace(input,repl, with); + char * path = StringTools::str_replace(input,repl, with); if(path != NULL) { strncpy(gFileInfos[j].path,path, 255); free(path); @@ -292,7 +146,7 @@ DECL_FUNCTION(int32_t, MCP_TitleList, uint32_t handle, uint32_t* outTitleCount, const char * indexedDevice = "mlc"; strcpy(template_title.indexedDevice,indexedDevice); - if(EndsWith(gFileInfos[j].name, ".wbf")) { + if(StringTools::EndsWith(gFileInfos[j].name, ".wbf")) { template_title.appType = MCP_APP_TYPE_GAME; } else { @@ -364,10 +218,13 @@ DECL_FUNCTION(int32_t, ACPCheckTitleLaunchByTitleListTypeEx, MCPTitleListType* t if(res >= 0) { request.filesize = ((uint32_t*)&info.length)[1]; request.fileoffset = ((uint32_t*)&info.offset)[1]; + loadFileIntoBuffer((title->titleId & 0xFFFFFFFF),"meta/iconTex.tga",gIconCache,sizeof(gIconCache)); } strncpy(request.path, gFileInfos[(uint32_t)(title->titleId & 0xFFFFFFFF)].path, 255); + + DEBUG_FUNCTION_LINE("Loading file %s size: %08X offset: %08X\n", request.path, request.filesize, request.fileoffset); DCFlushRange(&request, sizeof(LOAD_REQUEST)); @@ -386,178 +243,16 @@ DECL_FUNCTION(int32_t, ACPCheckTitleLaunchByTitleListTypeEx, MCPTitleListType* t } - -void unmountRomfs(uint32_t id) { - if(id >= FILE_INFO_SIZE){ - return; - } - if(gFileInfos[id].romfsMounted) { - char romName [10]; - snprintf(romName,10,"%08X", id); - DEBUG_FUNCTION_LINE("Unmounting %s\n", romName); - int res = romfsUnmount(romName); - DEBUG_FUNCTION_LINE("res: %d\n",res); - gFileInfos[id].romfsMounted = false; - } -} - -void unmountAllRomfs() { - for(int i = 0; i < FILE_INFO_SIZE; i++) { - unmountRomfs(i); - } -} - - -bool file_exist (char *filename) { - struct stat buffer; - return (stat (filename, &buffer) == 0); -} - - -bool initCompressedFileReadInformation(fileReadInformation * info){ - if(info == NULL || !info->compressed){ - info->cInitDone = false; - return false; - } - if(info->cInitDone){ - return true; - } - /* allocate inflate state */ - info->strm.zalloc = Z_NULL; - info->strm.zfree = Z_NULL; - info->strm.opaque = Z_NULL; - info->strm.avail_in = 0; - info->strm.next_in = Z_NULL; - int ret = inflateInit2(&info->strm, MAX_WBITS | 16); //gzip - if (ret != Z_OK){ - DEBUG_FUNCTION_LINE("ret != Z_OK\n"); - info->cInitDone = false; - return false; - } - info->cInitDone = true; - return true; -} - -int32_t FSOpenFile_for_ID(uint32_t id, const char * filepath, int * handle) { - if(!mountRomfs(id)) { - return -1; - } - char romName [10]; - snprintf(romName,10,"%08X", id); - - char * test = (char *) malloc(strlen(filepath)+1); - char last = 0; - int j = 0; - for(int i = 0; filepath[i] != 0; i++) { - if(filepath[i] == '/' ) { - if(filepath[i] != last) { - test[j++] = filepath[i]; - } - } else { - test[j++] = filepath[i]; - } - last = filepath[i]; - } - test[j++] = 0; - - char buffer [256]; - snprintf(buffer,256,"%s:/%s.gz",romName, test); - - bool nonCompressed = false; - if(!file_exist(buffer)) { - snprintf(buffer,256,"%s:/%s",romName, test); - if(!file_exist(buffer)) { - return -3; - } - nonCompressed = true; - } - - int fd = open(buffer,0); - if(fd >= 0) { - DEBUG_FUNCTION_LINE("Opened %s from %s \n",buffer, romName ); - int slot = fileReadInformation_getSlot(); - if(slot < 0){ - return -5; - } - fileReadInformation * info = &gFileReadInformation[slot]; - info->fd = fd; - if(!nonCompressed){ - info->compressed = true; - initCompressedFileReadInformation(info); - DEBUG_FUNCTION_LINE("Init compressed, got slot %d\n", slot); - }else{ - info->cInitDone = true; - } - *handle = 0xFF000000 + slot; - return 0; - } - - - /* - DEBUG_FUNCTION_LINE("OPENING %s\n", buffer); - - std::istream* is = new zstr::ifstream(buffer); - DEBUG_FUNCTION_LINE("OPENED %s\n", buffer); - if(is != NULL) { - for(int i = 0; i<100; i++) { - if(gFileHandleToStream[i] == NULL) { - DEBUG_FUNCTION_LINE("Set stream to id %d\n",i); - gFileHandleToStream[i] = is; - *handle = 0xFF000000 + i; - return 0; - } - } - } - DEBUG_FUNCTION_LINE("Failed to find handle \n");*/ - - return -2; -} - -int32_t getRPXInfoForID(uint32_t id, romfs_fileInfo * info) { - if(!mountRomfs(id)) { - return -1; - } - DIR *dir; - struct dirent *entry; - char romName [10]; - snprintf(romName,10,"%08X", id); - - char root[12]; - snprintf(root,12,"%08X:/", id); - - if (!(dir = opendir(root))) { - return -2; - } - bool found = false; - int res = -3; - while ((entry = readdir(dir)) != NULL) { - if(EndsWith(entry->d_name, ".rpx")) { - if(romfs_GetFileInfoPerPath(romName, entry->d_name, info) >= 0) { - found = true; - res = 0; - } - break; - } - } - - closedir(dir); - - if(!found) { - return -4; - } - return res; -} - DECL_FUNCTION(int, FSOpenFile, FSClient *client, FSCmdBlock *block, char *path, const char *mode, int *handle, int error) { char * start = "/vol/storage_mlc01/sys/title/0005000F"; char * icon = ".tga"; char * iconTex = "iconTex.tga"; char * sound = ".btsnd"; - if(EndsWith(path,icon) || EndsWith(path,sound)) { - if(strncmp(path,start,strlen(start)) == 0/* || (gHomebrewLaunched && EndsWith(path,iconTex))*/) { + if(StringTools::EndsWith(path,icon) || StringTools::EndsWith(path,sound)) { + if(strncmp(path,start,strlen(start)) == 0) { int res = FS_STATUS_NOT_FOUND; - if(EndsWith(path,iconTex)) { + if(StringTools::EndsWith(path,iconTex)) { // fallback to dummy icon if loaded homebrew is no .wbf //*handle = 0x1337; res = FS_STATUS_NOT_FOUND; @@ -572,6 +267,17 @@ DECL_FUNCTION(int, FSOpenFile, FSClient *client, FSCmdBlock *block, char *path, return res; } return FS_STATUS_OK; + } else if(gHomebrewLaunched) { + socket_lib_init(); + log_init(); + if(StringTools::EndsWith(path,iconTex)) { + *handle = 0x13371337; + DEBUG_FUNCTION_LINE("yooo let's do it\n"); + return FS_STATUS_OK; + }else{ + DEBUG_FUNCTION_LINE("%s\n",path); + } + } } @@ -579,147 +285,48 @@ DECL_FUNCTION(int, FSOpenFile, FSClient *client, FSCmdBlock *block, char *path, return result; } -bool DeInitFile(int slot){ - if(gFileReadInformation[slot].compressed && gFileReadInformation[slot].cInitDone){ - /* clean up and return */ - (void)inflateEnd(&(gFileReadInformation[slot].strm)); - } - - close(gFileReadInformation[slot].fd); - gFileReadInformation[slot].inUse = false; - memset(&gFileReadInformation[slot],0, sizeof(fileReadInformation)); - return true; -} - DECL_FUNCTION(FSStatus, FSCloseFile, FSClient *client, FSCmdBlock *block, FSFileHandle handle, uint32_t flags) { - if(handle == 0x1337) { - //return FS_STATUS_OK; + if(handle == 0x13371337) { + return FS_STATUS_OK; } if((handle & 0xFF000000) == 0xFF000000) { - int32_t fd = (handle & 0x00FFFFFF); - DEBUG_FUNCTION_LINE("Close %d\n", fd); + int32_t fd = (handle & 0x00000FFF); + int32_t romid = (handle & 0x00FFF000) >> 12; + DEBUG_FUNCTION_LINE("Close %d %d\n", fd, romid); DeInitFile(fd); - unmountAllRomfs(); + if(gFileInfos[romid].openedFiles--) { + if(gFileInfos[romid].openedFiles <= 0) { + DEBUG_FUNCTION_LINE("unmount romfs no more handles\n"); + unmountRomfs(romid); + } + } + //unmountAllRomfs(); return FS_STATUS_OK; } return real_FSCloseFile(client,block,handle,flags); } -bool initFile(int slot){ - if(gFileReadInformation[slot].compressed && !gFileReadInformation[slot].cInitDone){ - initCompressedFileReadInformation(&gFileReadInformation[slot]); - if(!gFileReadInformation[slot].cInitDone){ - DEBUG_FUNCTION_LINE("Failed to init\n"); - return false; - } - } - return true; -} - - - -int readFile(int slot, uint8_t * buffer, uint32_t size){ - fileReadInformation * info = &gFileReadInformation[slot]; - if(!info->compressed){ - //DEBUG_FUNCTION_LINE("non compressed\n"); - return read(info->fd, buffer, size); - }else{ - int startValue = info->strm.total_out; - int newSize = 0; - int ret = 0; - //DEBUG_FUNCTION_LINE("We want to read %d\n", size); - //DEBUG_FUNCTION_LINE("startValue %d \n",startValue); - do { - int CHUNK = 0x1000; - int nextOut = CHUNK; - if(nextOut > size){ - nextOut = size; - } - //DEBUG_FUNCTION_LINE("nextOut = %d\n",nextOut); - if(info->strm.avail_in == 0){ - //DEBUG_FUNCTION_LINE("Reading %d from compressed stream\n",CHUNK); - info->strm.avail_in = read(info->fd, info->in, CHUNK); - if (info->strm.avail_in == 0){ - DEBUG_FUNCTION_LINE("strm.avail_in is 0\n"); - break; - } - info->strm.next_in = info->in; - } - //DEBUG_FUNCTION_LINE("info->strm.avail_in = %d\n",info->strm.avail_in); - //DEBUG_FUNCTION_LINE("info->strm.next_in = %d\n",info->strm.next_in); - - /* run inflate() on input until output buffer not full */ - do { - //DEBUG_FUNCTION_LINE("newSize %d, size %d, info->strm.avail_out %d\n", newSize, size, info->strm.avail_out); - - if(nextOut > size - newSize){ - nextOut = size - newSize; - } - - info->strm.avail_out = nextOut; - //DEBUG_FUNCTION_LINE("info->strm.avail_out = %d\n",info->strm.avail_out); - info->strm.next_out = (buffer + newSize); - //DEBUG_FUNCTION_LINE("info->strm.next_out = %08X\n",info->strm.next_out); - ret = inflate(&info->strm, Z_NO_FLUSH); - //DEBUG_FUNCTION_LINE("ret = %d\n",ret); - if(ret == Z_STREAM_ERROR){ - DEBUG_FUNCTION_LINE("Z_STREAM_ERROR\n"); - return (FSStatus)0; - } - - switch (ret) { - case Z_NEED_DICT: - DEBUG_FUNCTION_LINE("Z_NEED_DICT\n"); - ret = Z_DATA_ERROR; /* and fall through */ - case Z_DATA_ERROR: - case Z_MEM_ERROR: - DEBUG_FUNCTION_LINE("Z_MEM_ERROR or Z_DATA_ERROR\n"); - (void)inflateEnd(&info->strm); - return (FSStatus) ret; - } - - int canBeWritten = CHUNK - info->strm.avail_out; - //DEBUG_FUNCTION_LINE("canBeWritten = %d\n",canBeWritten); - - newSize = info->strm.total_out - startValue; - if(newSize == size){ - //DEBUG_FUNCTION_LINE("newSize was as wanted %d\n", newSize); - break; - } - nextOut = CHUNK; - if(newSize + nextOut >= (size)){ - nextOut = (size) - newSize; - } - //DEBUG_FUNCTION_LINE("newSize = %d\n",newSize); - //DEBUG_FUNCTION_LINE("nextOut = %d\n",nextOut); - } while (info->strm.avail_out == 0 && newSize < (size)); - - /* done when inflate() says it's done */ - } while (ret != Z_STREAM_END && newSize < size); - - return newSize; - } -} - DECL_FUNCTION(FSStatus, FSReadFile, FSClient *client, FSCmdBlock *block, uint8_t *buffer, uint32_t size, uint32_t count, FSFileHandle handle,uint32_t unk1, uint32_t flags) { - if(handle == 0x1337) { + if(handle == 0x13371337) { int cpySize = size*count; - if(iconTex_tga_size < cpySize) { - cpySize = iconTex_tga_size; + if(sizeof(gIconCache) < cpySize) { + cpySize = sizeof(gIconCache); } - memcpy(buffer, iconTex_tga, cpySize); + memcpy(buffer, gIconCache, cpySize); + DEBUG_FUNCTION_LINE("DUMMY\n"); return (FSStatus)(cpySize/size); } if((handle & 0xFF000000) == 0xFF000000) { - int32_t fd = (handle & 0x00FFFFFF); + int32_t fd = (handle & 0x00000FFF); + int32_t romid = (handle & 0x00FFF000) >> 12; + + DEBUG_FUNCTION_LINE("READ %d from %d rom: %d\n", size*count, fd, romid); - initFile(fd); int readSize = readFile(fd, buffer, (size*count)); - //DEBUG_FUNCTION_LINE("READ %d from %d result %d\n", size*count, fd, readSize); return (FSStatus)(readSize / size); } FSStatus result = real_FSReadFile(client, block, buffer, size, count, handle, unk1, flags); @@ -744,8 +351,6 @@ DECL_FUNCTION(int32_t, ACPGetTitleMetaDirByDevice, uint32_t titleid_upper, uint3 return result; } - - DECL_FUNCTION(int32_t, _SYSLaunchTitleByPathFromLauncher, char* pathToLoad, uint32_t u2) { const char * start = "/custom/"; if(strncmp(pathToLoad,start,strlen(start)) == 0) { diff --git a/src/readFileWrapper.cpp b/src/readFileWrapper.cpp new file mode 100644 index 0000000..4f50acd --- /dev/null +++ b/src/readFileWrapper.cpp @@ -0,0 +1,244 @@ +#include "readFileWrapper.h" +#include "fs/FSUtils.h" +#include "utils/logger.h" +#include +#include +#include +#include +#include +#include +#include "romfs_helper.h" + +fileReadInformation gFileReadInformation[FILE_READ_INFO_SIZE] __attribute__((section(".data"))); + +int readFile(int slot, uint8_t * buffer, uint32_t size) { + fileReadInformation * info = &gFileReadInformation[slot]; + if(!info->compressed) { + //DEBUG_FUNCTION_LINE("non compressed\n"); + return read(info->fd, buffer, size); + } else { + int startValue = info->strm.total_out; + int newSize = 0; + int ret = 0; + //DEBUG_FUNCTION_LINE("We want to read %d\n", size); + //DEBUG_FUNCTION_LINE("startValue %d \n",startValue); + do { + int CHUNK = 0x1000; + int nextOut = CHUNK; + if(nextOut > size) { + nextOut = size; + } + //DEBUG_FUNCTION_LINE("nextOut = %d\n",nextOut); + if(info->strm.avail_in == 0) { + //DEBUG_FUNCTION_LINE("Reading %d from compressed stream\n",CHUNK); + info->strm.avail_in = read(info->fd, info->in, CHUNK); + if (info->strm.avail_in == 0) { + DEBUG_FUNCTION_LINE("strm.avail_in is 0\n"); + break; + } + info->strm.next_in = info->in; + } + //DEBUG_FUNCTION_LINE("info->strm.avail_in = %d\n",info->strm.avail_in); + //DEBUG_FUNCTION_LINE("info->strm.next_in = %d\n",info->strm.next_in); + + /* run inflate() on input until output buffer not full */ + do { + //DEBUG_FUNCTION_LINE("newSize %d, size %d, info->strm.avail_out %d\n", newSize, size, info->strm.avail_out); + + if(nextOut > size - newSize) { + nextOut = size - newSize; + } + + info->strm.avail_out = nextOut; + //DEBUG_FUNCTION_LINE("info->strm.avail_out = %d\n",info->strm.avail_out); + info->strm.next_out = (buffer + newSize); + //DEBUG_FUNCTION_LINE("info->strm.next_out = %08X\n",info->strm.next_out); + ret = inflate(&info->strm, Z_NO_FLUSH); + //DEBUG_FUNCTION_LINE("ret = %d\n",ret); + if(ret == Z_STREAM_ERROR) { + DEBUG_FUNCTION_LINE("Z_STREAM_ERROR\n"); + return 0; + } + + switch (ret) { + case Z_NEED_DICT: + DEBUG_FUNCTION_LINE("Z_NEED_DICT\n"); + ret = Z_DATA_ERROR; /* and fall through */ + case Z_DATA_ERROR: + case Z_MEM_ERROR: + DEBUG_FUNCTION_LINE("Z_MEM_ERROR or Z_DATA_ERROR\n"); + (void)inflateEnd(&info->strm); + return ret; + } + + int canBeWritten = CHUNK - info->strm.avail_out; + //DEBUG_FUNCTION_LINE("canBeWritten = %d\n",canBeWritten); + + newSize = info->strm.total_out - startValue; + if(newSize == size) { + //DEBUG_FUNCTION_LINE("newSize was as wanted %d\n", newSize); + break; + } + nextOut = CHUNK; + if(newSize + nextOut >= (size)) { + nextOut = (size) - newSize; + } + //DEBUG_FUNCTION_LINE("newSize = %d\n",newSize); + //DEBUG_FUNCTION_LINE("nextOut = %d\n",nextOut); + } while (info->strm.avail_out == 0 && newSize < (size)); + + /* done when inflate() says it's done */ + } while (ret != Z_STREAM_END && newSize < size); + + return newSize; + } +} + + +bool DeInitFile(int slot) { + if(gFileReadInformation[slot].compressed && gFileReadInformation[slot].cInitDone) { + /* clean up and return */ + (void)inflateEnd(&(gFileReadInformation[slot].strm)); + } + + close(gFileReadInformation[slot].fd); + gFileReadInformation[slot].inUse = false; + memset(&gFileReadInformation[slot],0, sizeof(fileReadInformation)); + return true; +} + + + +void DeInitAllFiles() { + for(int i = 0; iinUse) { + DeInitFile(i); + } + } +} + +int fileReadInformation_getSlot() { + for(int i = 0; i<32; i++) { + if(gFileReadInformation[i].inUse == false) { + gFileReadInformation[i].inUse = true; + return i; + } + } + return -1; +} + + +bool initCompressedFileReadInformation(fileReadInformation * info) { + if(info == NULL || !info->compressed) { + info->cInitDone = false; + return false; + } + if(info->cInitDone) { + return true; + } + /* allocate inflate state */ + info->strm.zalloc = Z_NULL; + info->strm.zfree = Z_NULL; + info->strm.opaque = Z_NULL; + info->strm.avail_in = 0; + info->strm.next_in = Z_NULL; + int ret = inflateInit2(&info->strm, MAX_WBITS | 16); //gzip + if (ret != Z_OK) { + DEBUG_FUNCTION_LINE("ret != Z_OK\n"); + info->cInitDone = false; + return false; + } + info->cInitDone = true; + return true; +} + + +int32_t loadFileIntoBuffer(uint32_t id, char * filepath, char * buffer, int sizeToRead) { + if(!mountRomfs(id)) { + return -1; + } + int handle = 0; + if(FSOpenFile_for_ID(id, filepath, &handle) != 0){ + return -2; + } + + int32_t fd = (handle & 0x00000FFF); + int32_t romid = (handle & 0x00FFF000) >> 12; + + DEBUG_FUNCTION_LINE("READ %d from %d rom: %d\n", sizeToRead, fd, romid); + + int readSize = readFile(fd, (uint8_t*)buffer, (sizeToRead)); + + DEBUG_FUNCTION_LINE("Close %d %d\n", fd, romid); + DeInitFile(fd); + if(gFileInfos[romid].openedFiles--){ + if(gFileInfos[romid].openedFiles <= 0){ + DEBUG_FUNCTION_LINE("unmount romfs no more handles\n"); + unmountRomfs(romid); + } + } + + return readSize; +} + + + + +int32_t FSOpenFile_for_ID(uint32_t id, const char * filepath, int * handle) { + if(!mountRomfs(id)) { + return -1; + } + char romName [10]; + snprintf(romName,10,"%08X", id); + + char * test = (char *) malloc(strlen(filepath)+1); + char last = 0; + int j = 0; + for(int i = 0; filepath[i] != 0; i++) { + if(filepath[i] == '/' ) { + if(filepath[i] != last) { + test[j++] = filepath[i]; + } + } else { + test[j++] = filepath[i]; + } + last = filepath[i]; + } + test[j++] = 0; + + char buffer [256]; + snprintf(buffer,256,"%s:/%s.gz",romName, test); + + bool nonCompressed = false; + if(!FSUtils::CheckFile(buffer)) { + snprintf(buffer,256,"%s:/%s",romName, test); + if(!FSUtils::CheckFile(buffer)) { + return -3; + } + nonCompressed = true; + } + + int fd = open(buffer,0); + if(fd >= 0) { + DEBUG_FUNCTION_LINE("Opened %s from %s \n",buffer, romName ); + int slot = fileReadInformation_getSlot(); + if(slot < 0) { + DEBUG_FUNCTION_LINE("Failed to get a slot\n"); + return -5; + } + fileReadInformation * info = &gFileReadInformation[slot]; + info->fd = fd; + if(!nonCompressed) { + info->compressed = true; + initCompressedFileReadInformation(info); + DEBUG_FUNCTION_LINE("Init compressed, got slot %d\n", slot); + } else { + info->cInitDone = true; + } + *handle = 0xFF000000 | (id << 12) | (slot & 0x00000FFF); + gFileInfos[id].openedFiles++; + return 0; + } + return -2; +} diff --git a/src/readFileWrapper.h b/src/readFileWrapper.h new file mode 100644 index 0000000..5cd47c1 --- /dev/null +++ b/src/readFileWrapper.h @@ -0,0 +1,37 @@ +#pragma once +#include +#include +#include + +typedef struct { + bool inUse; + int fd; + bool compressed; + bool cInitDone; + bool cCloseDone; + z_stream strm; + unsigned char in[0x1000]; +} fileReadInformation; + + +#define FILE_READ_INFO_SIZE 32 + +extern fileReadInformation gFileReadInformation[FILE_READ_INFO_SIZE]; + + +bool initFile(int slot); + +int readFile(int slot, uint8_t * buffer, uint32_t size); + +bool DeInitFile(int slot); + +void DeInitAllFiles(); + +int32_t loadFileIntoBuffer(uint32_t id, char * filepath, char * buffer, int sizeToRead) ; + +int32_t FSOpenFile_for_ID(uint32_t id, const char * filepath, int * handle); + +int fileReadInformation_getSlot(); + + +bool initCompressedFileReadInformation(fileReadInformation * info); diff --git a/src/romfs_dev.c b/src/romfs_dev.c deleted file mode 100644 index 699ea4d..0000000 --- a/src/romfs_dev.c +++ /dev/null @@ -1,702 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "romfs_dev.h" - -typedef enum { - RomfsSource_FileDescriptor, -} RomfsSource; - -typedef struct romfs_mount { - devoptab_t device; - bool setup; - RomfsSource fd_type; - int32_t id; - int32_t fd; - time_t mtime; - uint64_t offset; - romfs_header header; - romfs_dir *cwd; - uint32_t *dirHashTable, *fileHashTable; - void *dirTable, *fileTable; - char name[32]; -} romfs_mount; - -extern int __system_argc; -extern char** __system_argv; - -//static char __thread __component[PATH_MAX+1]; -static char __component[PATH_MAX+1]; - -#define romFS_root(m) ((romfs_dir*)(m)->dirTable) -#define romFS_dir(m,x) ((romfs_dir*) ((uint8_t*)(m)->dirTable + (x))) -#define romFS_file(m,x) ((romfs_file*)((uint8_t*)(m)->fileTable + (x))) -#define romFS_none ((uint32_t)~0) -#define romFS_dir_mode (S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH) -#define romFS_file_mode (S_IFREG | S_IRUSR | S_IRGRP | S_IROTH) - -uint64_t swapLong(uint64_t X) { - uint64_t x = (uint64_t) X; - x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32; - x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16; - x = (x & 0x00FF00FF00FF00FF) << 8 | (x & 0xFF00FF00FF00FF00) >> 8; - return x; -} - -#define REVERSE_SHORT(n) ((unsigned short) (((n & 0xFF) << 8) | \ - ((n & 0xFF00) >> 8))) -#define REVERSE_INT(n) ((unsigned int) (((n & 0xFF) << 24) | \ - ((n & 0xFF00) << 8) | \ - ((n & 0xFF0000) >> 8) | \ - ((n & 0xFF000000) >> 24))) - -static ssize_t _romfs_read(romfs_mount *mount, uint64_t offset, void* buffer, uint64_t size) { - uint64_t pos = mount->offset + offset; - size_t _read = 0; - if(mount->fd_type == RomfsSource_FileDescriptor) { - off_t seek_offset = lseek(mount->fd, pos, SEEK_SET); - if(pos != seek_offset) { - return -1; - } - _read = read(mount->fd, buffer, size); - } - return _read; -} - -static bool _romfs_read_chk(romfs_mount *mount, uint64_t offset, void* buffer, uint64_t size) { - return _romfs_read(mount, offset, buffer, size) == size; -} - -//----------------------------------------------------------------------------- - -static int romfs_open(struct _reent *r, void *fileStruct, const char *path, int flags, int mode); -static int romfs_close(struct _reent *r, void *fd); -static ssize_t romfs_read(struct _reent *r, void *fd, char *ptr, size_t len); -static off_t romfs_seek(struct _reent *r, void *fd, off_t pos, int dir); -static int romfs_fstat(struct _reent *r, void *fd, struct stat *st); -static int romfs_stat(struct _reent *r, const char *path, struct stat *st); -static int romfs_chdir(struct _reent *r, const char *path); -static DIR_ITER* romfs_diropen(struct _reent *r, DIR_ITER *dirState, const char *path); -static int romfs_dirreset(struct _reent *r, DIR_ITER *dirState); -static int romfs_dirnext(struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *filestat); -static int romfs_dirclose(struct _reent *r, DIR_ITER *dirState); - -typedef struct { - romfs_mount *mount; - romfs_file *file; - uint64_t offset, pos; -} romfs_fileobj; - -typedef struct { - romfs_mount *mount; - romfs_dir* dir; - uint32_t state; - uint32_t childDir; - uint32_t childFile; -} romfs_diriter; - -static devoptab_t romFS_devoptab = { - .structSize = sizeof(romfs_fileobj), - .open_r = romfs_open, - .close_r = romfs_close, - .read_r = romfs_read, - .seek_r = romfs_seek, - .fstat_r = romfs_fstat, - .stat_r = romfs_stat, - .chdir_r = romfs_chdir, - .dirStateSize = sizeof(romfs_diriter), - .diropen_r = romfs_diropen, - .dirreset_r = romfs_dirreset, - .dirnext_r = romfs_dirnext, - .dirclose_r = romfs_dirclose, -}; - -static bool romfs_initialised = false; -static romfs_mount romfs_mounts[300]; - -//----------------------------------------------------------------------------- - -static int32_t romfsMountCommon(const char *name, romfs_mount *mount); -static void romfsInitMtime(romfs_mount *mount); - -static void _romfsResetMount(romfs_mount *mount, int32_t id) { - memset(mount, 0, sizeof(*mount)); - memcpy(&mount->device, &romFS_devoptab, sizeof(romFS_devoptab)); - mount->device.name = mount->name; - mount->device.deviceData = mount; - mount->id = id; -} - -static void _romfsInit(void) { - uint32_t i; - uint32_t total = sizeof(romfs_mounts) / sizeof(romfs_mount); - - if(!romfs_initialised) { - for(i = 0; i < total; i++) { - _romfsResetMount(&romfs_mounts[i], i); - } - - romfs_initialised = true; - } -} - -static romfs_mount *romfsFindMount(const char *name) { - uint32_t i; - uint32_t total = sizeof(romfs_mounts) / sizeof(romfs_mount); - romfs_mount *mount = NULL; - - _romfsInit(); - - for(i=0; isetup) - return mount; - } else if(mount->setup) { //Find the mount with the input name. - if(strncmp(mount->name, name, sizeof(mount->name))==0) - return mount; - } - } - - return NULL; -} - -__attribute__((weak)) const char* __romfs_path = NULL; - -static romfs_mount* romfs_alloc(void) { - return romfsFindMount(NULL); -} - -static void romfs_free(romfs_mount *mount) { - free(mount->fileTable); - free(mount->fileHashTable); - free(mount->dirTable); - free(mount->dirHashTable); - _romfsResetMount(mount, mount->id); -} - -static void romfs_mountclose(romfs_mount *mount) { - if(mount->fd_type == RomfsSource_FileDescriptor) { - close(mount->fd); - } - romfs_free(mount); -} - -int32_t romfsMount(const char *name, const char * filepath) { - romfs_mount *mount = romfs_alloc(); - if(mount == NULL) - return 99; - - // Regular RomFS - mount->fd_type = RomfsSource_FileDescriptor; - - mount->fd = open(filepath, 0); - if (mount->fd == -1) { - romfs_free(mount); - return -1; - } - - romfsInitMtime(mount); - return romfsMountCommon(name, mount); - -_fail0: - romfs_mountclose(mount); - return 10; -} - -int32_t romfsMountCommon(const char *name, romfs_mount *mount) { - memset(mount->name, 0, sizeof(mount->name)); - strncpy(mount->name, name, sizeof(mount->name)-1); - - if (_romfs_read(mount, 0, &mount->header, sizeof(mount->header)) != sizeof(mount->header)) - goto fail; - - mount->dirHashTable = (uint32_t*)malloc(swapLong(mount->header.dirHashTableSize)); - if (!mount->dirHashTable) - goto fail; - if (!_romfs_read_chk(mount, swapLong(mount->header.dirHashTableOff), mount->dirHashTable, swapLong(mount->header.dirHashTableSize))) - goto fail; - - mount->dirTable = malloc(swapLong(mount->header.dirTableSize)); - if (!mount->dirTable) - goto fail; - if (!_romfs_read_chk(mount, swapLong(mount->header.dirTableOff), mount->dirTable, swapLong(mount->header.dirTableSize))) - goto fail; - mount->fileHashTable = (uint32_t*)malloc(swapLong(mount->header.fileHashTableSize)); - if (!mount->fileHashTable) - goto fail; - if (!_romfs_read_chk(mount, swapLong(mount->header.fileHashTableOff), mount->fileHashTable, swapLong(mount->header.fileHashTableSize))) - goto fail; - mount->fileTable = malloc(swapLong(mount->header.fileTableSize)); - if (!mount->fileTable) - goto fail; - - if (!_romfs_read_chk(mount, swapLong(mount->header.fileTableOff), mount->fileTable, swapLong(mount->header.fileTableSize))) - goto fail; - mount->cwd = romFS_root(mount); - - // add device if this is the first one - if(AddDevice(&mount->device) < 0) - goto fail; - mount->setup = true; - return 0; - -fail: - romfs_mountclose(mount); - return 10; -} - -static void romfsInitMtime(romfs_mount *mount) { - mount->mtime = time(NULL); -} - -int32_t romfsUnmount(const char *name) { - romfs_mount *mount; - char tmpname[34]; - - mount = romfsFindMount(name); - if (mount == NULL) - return -1; - - // Remove device - memset(tmpname, 0, sizeof(tmpname)); - strncpy(tmpname, mount->name, sizeof(tmpname)-2); - strncat(tmpname, ":", sizeof(tmpname)-strlen(tmpname)-1); - - RemoveDevice(tmpname); - - romfs_mountclose(mount); - - return 0; -} - -//----------------------------------------------------------------------------- - -static uint32_t calcHash(uint32_t parent, const uint8_t* name, uint32_t namelen, uint32_t total) { - uint32_t hash = parent ^ 123456789; - uint32_t i; - for (i = 0; i < namelen; i ++) { - hash = (hash >> 5) | (hash << 27); - hash ^= name[i]; - } - return hash % total; -} - -static romfs_dir* searchForDir(romfs_mount *mount, romfs_dir* parent, const uint8_t* name, uint32_t namelen) { - uint64_t parentOff = (uintptr_t)parent - (uintptr_t)mount->dirTable; - uint32_t hash = calcHash(parentOff, name, namelen, swapLong(mount->header.dirHashTableSize)/4); - romfs_dir* curDir = NULL; - uint32_t curOff; - for (curOff = REVERSE_INT(mount->dirHashTable[hash]); curOff != romFS_none; curOff = REVERSE_INT(curDir->nextHash)) { - curDir = romFS_dir(mount, curOff); - if (REVERSE_INT(curDir->parent) != parentOff) - continue; - if (REVERSE_INT(curDir->nameLen) != namelen) - continue; - if (memcmp(curDir->name, name, namelen) != 0) - continue; - return curDir; - } - return NULL; -} - -static romfs_file* searchForFile(romfs_mount *mount, romfs_dir* parent, const uint8_t* name, uint32_t namelen) { - uint64_t parentOff = (uintptr_t)parent - (uintptr_t)mount->dirTable; - uint32_t hash = calcHash(parentOff, name, namelen, swapLong(mount->header.fileHashTableSize)/4); - romfs_file* curFile = NULL; - uint32_t curOff; - for (curOff = REVERSE_INT(mount->fileHashTable[hash]); curOff != romFS_none; curOff = REVERSE_INT(curFile->nextHash)) { - curFile = romFS_file(mount, curOff); - if (REVERSE_INT(curFile->parent) != parentOff) - continue; - if (REVERSE_INT(curFile->nameLen) != namelen) - continue; - if (memcmp(curFile->name, name, namelen) != 0) - continue; - return curFile; - } - return NULL; -} - -static int navigateToDir(romfs_mount *mount, romfs_dir** ppDir, const char** pPath, bool isDir) { - char* colonPos = strchr(*pPath, ':'); - if (colonPos) - *pPath = colonPos+1; - if (!**pPath) - return EILSEQ; - - *ppDir = mount->cwd; - if (**pPath == '/') { - *ppDir = romFS_root(mount); - (*pPath)++; - } - - while (**pPath) { - char* slashPos = strchr(*pPath, '/'); - char* component = __component; - - if (slashPos) { - uint32_t len = slashPos - *pPath; - if (!len) - return EILSEQ; - if (len > PATH_MAX) - return ENAMETOOLONG; - - memcpy(component, *pPath, len); - component[len] = 0; - *pPath = slashPos+1; - } else if (isDir) { - component = (char*)*pPath; - *pPath += strlen(component); - } else - return 0; - - if (component[0]=='.') { - if (!component[1]) - continue; - if (component[1]=='.' && !component[2]) { - *ppDir = romFS_dir(mount, REVERSE_INT((*ppDir)->parent)); - continue; - } - } - - *ppDir = searchForDir(mount, *ppDir, (uint8_t*)component, strlen(component)); - if (!*ppDir) - return EEXIST; - } - - if (!isDir && !**pPath) - return EILSEQ; - - return 0; -} - -static ino_t dir_inode(romfs_mount *mount, romfs_dir *dir) { - return (uint32_t*)dir - (uint32_t*)mount->dirTable; -} - -static off_t dir_size(romfs_dir *dir) { - return sizeof(romfs_dir) + (REVERSE_INT(dir->nameLen)+3)/4; -} - -static nlink_t dir_nlink(romfs_mount *mount, romfs_dir *dir) { - nlink_t count = 2; // one for self, one for parent - uint32_t offset = REVERSE_INT(dir->childDir); - - while(offset != romFS_none) { - romfs_dir *tmp = romFS_dir(mount, offset); - ++count; - offset = REVERSE_INT(tmp->sibling); - } - - offset = REVERSE_INT(dir->childFile); - while(offset != romFS_none) { - romfs_file *tmp = romFS_file(mount, offset); - ++count; - offset = REVERSE_INT(tmp->sibling); - } - - return count; -} - -static ino_t file_inode(romfs_mount *mount, romfs_file *file) { - return ((uint32_t*)file - (uint32_t*)mount->fileTable) + swapLong(mount->header.dirTableSize)/4; -} - -int romfs_GetFileInfoPerPath(const char* romfs, const char *path, romfs_fileInfo* out) { - if(out == NULL){ - return -1; - } - romfs_mount* mount = (romfs_mount*)romfsFindMount(romfs); - if(mount == NULL){ - return -2; - } - romfs_dir* curDir = NULL; - int errno2 = navigateToDir(mount, &curDir, &path, false); - if (errno2 != 0){ - return -3; - } - - romfs_file* file = searchForFile(mount, curDir, (uint8_t*)path, strlen(path)); - if (!file) { - return -4; - } - - out->length = swapLong(file->dataSize); - out->offset = swapLong(mount->header.fileDataOff) + swapLong(file->dataOff); - - return 0; -} - - -//----------------------------------------------------------------------------- - -int romfs_open(struct _reent *r, void *fileStruct, const char *path, int flags, int mode) { - romfs_fileobj* fileobj = (romfs_fileobj*)fileStruct; - - fileobj->mount = (romfs_mount*)r->deviceData; - - if ((flags & O_ACCMODE) != O_RDONLY) { - r->_errno = EROFS; - return -1; - } - - romfs_dir* curDir = NULL; - r->_errno = navigateToDir(fileobj->mount, &curDir, &path, false); - if (r->_errno != 0) - return -1; - - romfs_file* file = searchForFile(fileobj->mount, curDir, (uint8_t*)path, strlen(path)); - if (!file) { - if(flags & O_CREAT) - r->_errno = EROFS; - else - r->_errno = ENOENT; - return -1; - } else if((flags & O_CREAT) && (flags & O_EXCL)) { - r->_errno = EEXIST; - return -1; - } - - fileobj->file = file; - fileobj->offset = swapLong(fileobj->mount->header.fileDataOff) + swapLong(file->dataOff); - fileobj->pos = 0; - - return 0; -} - -int romfs_close(struct _reent *r, void *fd) { - return 0; -} - -ssize_t romfs_read(struct _reent *r, void *fd, char *ptr, size_t len) { - romfs_fileobj* file = (romfs_fileobj*)fd; - uint64_t endPos = file->pos + len; - - /* check if past end-of-file */ - if(file->pos >= swapLong(file->file->dataSize)) - return 0; - - /* truncate the read to end-of-file */ - if(endPos > swapLong(file->file->dataSize)) - endPos = swapLong(file->file->dataSize); - len = endPos - file->pos; - - ssize_t adv = _romfs_read(file->mount, file->offset + file->pos, ptr, len); - if(adv >= 0) { - file->pos += adv; - return adv; - } - - r->_errno = EIO; - return -1; -} - -off_t romfs_seek(struct _reent *r, void *fd, off_t pos, int dir) { - romfs_fileobj* file = (romfs_fileobj*)fd; - off_t start; - switch (dir) { - case SEEK_SET: - start = 0; - break; - - case SEEK_CUR: - start = file->pos; - break; - - case SEEK_END: - start = swapLong(file->file->dataSize); - break; - - default: - r->_errno = EINVAL; - return -1; - } - - /* don't allow negative position */ - if(pos < 0) { - if(start + pos < 0) { - r->_errno = EINVAL; - return -1; - } - } - /* check for overflow */ - else if(INT64_MAX - pos < start) { - r->_errno = EOVERFLOW; - return -1; - } - - file->pos = start + pos; - return file->pos; -} - -int romfs_fstat(struct _reent *r, void *fd, struct stat *st) { - romfs_fileobj* file = (romfs_fileobj*)fd; - memset(st, 0, sizeof(struct stat)); - st->st_ino = file_inode(file->mount, file->file); - st->st_mode = romFS_file_mode; - st->st_nlink = 1; - st->st_size = (off_t)swapLong(file->file->dataSize); - st->st_blksize = 512; - st->st_blocks = (st->st_blksize + 511) / 512; - st->st_atime = st->st_mtime = st->st_ctime = file->mount->mtime; - - return 0; -} - -int romfs_stat(struct _reent *r, const char *path, struct stat *st) { - romfs_mount* mount = (romfs_mount*)r->deviceData; - romfs_dir* curDir = NULL; - r->_errno = navigateToDir(mount, &curDir, &path, false); - if(r->_errno != 0) - return -1; - - romfs_dir* dir = searchForDir(mount, curDir, (uint8_t*)path, strlen(path)); - if(dir) { - memset(st, 0, sizeof(*st)); - st->st_ino = dir_inode(mount, dir); - st->st_mode = romFS_dir_mode; - st->st_nlink = dir_nlink(mount, dir); - st->st_size = dir_size(dir); - st->st_blksize = 512; - st->st_blocks = (st->st_blksize + 511) / 512; - st->st_atime = st->st_mtime = st->st_ctime = mount->mtime; - - return 0; - } - - romfs_file* file = searchForFile(mount, curDir, (uint8_t*)path, strlen(path)); - if(file) { - memset(st, 0, sizeof(*st)); - st->st_ino = file_inode(mount, file); - st->st_mode = romFS_file_mode; - st->st_nlink = 1; - st->st_size = swapLong(file->dataSize); - st->st_blksize = 512; - st->st_blocks = (st->st_blksize + 511) / 512; - st->st_atime = st->st_mtime = st->st_ctime = mount->mtime; - - return 0; - } - - r->_errno = ENOENT; - return 1; -} - -int romfs_chdir(struct _reent *r, const char *path) { - romfs_mount* mount = (romfs_mount*)r->deviceData; - romfs_dir* curDir = NULL; - r->_errno = navigateToDir(mount, &curDir, &path, false); - if (r->_errno != 0) - return -1; - - mount->cwd = curDir; - return 0; -} - -DIR_ITER* romfs_diropen(struct _reent *r, DIR_ITER *dirState, const char *path) { - romfs_diriter* iter = (romfs_diriter*)(dirState->dirStruct); - romfs_dir* curDir = NULL; - iter->mount = (romfs_mount*)r->deviceData; - - r->_errno = navigateToDir(iter->mount, &curDir, &path, true); - if(r->_errno != 0) - return NULL; - - iter->dir = curDir; - iter->state = 0; - iter->childDir = REVERSE_INT(curDir->childDir); - iter->childFile = REVERSE_INT(curDir->childFile); - - return dirState; -} - -int romfs_dirreset(struct _reent *r, DIR_ITER *dirState) { - romfs_diriter* iter = (romfs_diriter*)(dirState->dirStruct); - - iter->state = 0; - iter->childDir = REVERSE_INT(iter->dir->childDir); - iter->childFile = REVERSE_INT(iter->dir->childFile); - - return 0; -} - -int romfs_dirnext(struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *filestat) { - romfs_diriter* iter = (romfs_diriter*)(dirState->dirStruct); - - if(iter->state == 0) { - /* '.' entry */ - memset(filestat, 0, sizeof(*filestat)); - filestat->st_ino = dir_inode(iter->mount, iter->dir); - filestat->st_mode = romFS_dir_mode; - - strcpy(filename, "."); - iter->state = 1; - return 0; - } else if(iter->state == 1) { - /* '..' entry */ - romfs_dir* dir = romFS_dir(iter->mount, REVERSE_INT(iter->dir->parent)); - - memset(filestat, 0, sizeof(*filestat)); - filestat->st_ino = dir_inode(iter->mount, dir); - filestat->st_mode = romFS_dir_mode; - - strcpy(filename, ".."); - iter->state = 2; - return 0; - } - - if(iter->childDir != romFS_none) { - romfs_dir* dir = romFS_dir(iter->mount, iter->childDir); - iter->childDir = REVERSE_INT(dir->sibling); - - memset(filestat, 0, sizeof(*filestat)); - filestat->st_ino = dir_inode(iter->mount, dir); - filestat->st_mode = romFS_dir_mode; - - memset(filename, 0, NAME_MAX); - - if(REVERSE_INT(dir->nameLen) >= NAME_MAX) { - r->_errno = ENAMETOOLONG; - return -1; - } - - strncpy(filename, (char*)dir->name, REVERSE_INT(dir->nameLen)); - - return 0; - } else if(iter->childFile != romFS_none) { - romfs_file* file = romFS_file(iter->mount, iter->childFile); - iter->childFile = REVERSE_INT(file->sibling); - - memset(filestat, 0, sizeof(*filestat)); - filestat->st_ino = file_inode(iter->mount, file); - filestat->st_mode = romFS_file_mode; - - memset(filename, 0, NAME_MAX); - - if(REVERSE_INT(file->nameLen) >= NAME_MAX) { - r->_errno = ENAMETOOLONG; - return -1; - } - - strncpy(filename, (char*)file->name, REVERSE_INT(file->nameLen)); - - return 0; - } - - r->_errno = ENOENT; - return -1; -} - -int romfs_dirclose(struct _reent *r, DIR_ITER *dirState) { - return 0; -} diff --git a/src/romfs_dev.h b/src/romfs_dev.h deleted file mode 100644 index 367f202..0000000 --- a/src/romfs_dev.h +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @file romfs_dev.h - * @brief RomFS driver. - * @author yellows8 - * @author mtheall - * @author fincs - * @copyright libnx Authors - */ -#pragma once - -#include - -/// RomFS header. -typedef struct { - uint64_t headerSize; ///< Size of the header. - uint64_t dirHashTableOff; ///< Offset of the directory hash table. - uint64_t dirHashTableSize; ///< Size of the directory hash table. - uint64_t dirTableOff; ///< Offset of the directory table. - uint64_t dirTableSize; ///< Size of the directory table. - uint64_t fileHashTableOff; ///< Offset of the file hash table. - uint64_t fileHashTableSize; ///< Size of the file hash table. - uint64_t fileTableOff; ///< Offset of the file table. - uint64_t fileTableSize; ///< Size of the file table. - uint64_t fileDataOff; ///< Offset of the file data. -} romfs_header; - -/// RomFS directory. -typedef struct { - uint32_t parent; ///< Offset of the parent directory. - uint32_t sibling; ///< Offset of the next sibling directory. - uint32_t childDir; ///< Offset of the first child directory. - uint32_t childFile; ///< Offset of the first file. - uint32_t nextHash; ///< Directory hash table pointer. - uint32_t nameLen; ///< Name length. - uint8_t name[]; ///< Name. (UTF-8) -} romfs_dir; - -/// RomFS file. -typedef struct { - uint32_t parent; ///< Offset of the parent directory. - uint32_t sibling; ///< Offset of the next sibling file. - uint64_t dataOff; ///< Offset of the file's data. - uint64_t dataSize; ///< Length of the file's data. - uint32_t nextHash; ///< File hash table pointer. - uint32_t nameLen; ///< Name length. - uint8_t name[]; ///< Name. (UTF-8) -} romfs_file; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Mounts the Application's RomFS. - * @param name Device mount name. - */ -int32_t romfsMount(const char *name, const char * path); - - -/** - * @brief Mounts RomFS from an open file. - * @param file FsFile of the RomFS image. - * @param offset Offset of the RomFS within the file. - * @param name Device mount name. -bool romfsMountFromFile(FsFile file, uint64_t offset, const char *name); -*/ -/* -static inline bool romfsInitFromFile(int32_t fd, uint64_t offset) { - return romfsMountFromFile(fd, offset, "romfs"); -}*/ - -/// Unmounts the RomFS device. -int32_t romfsUnmount(const char *name); -/* -static inline bool romfsExit(void) { - return romfsUnmount("romfs"); -}*/ - -/// RomFS file. -typedef struct { - uint64_t length; ///< Offset of the file's data. - uint64_t offset; ///< Length of the file's data. -} romfs_fileInfo; - -int romfs_GetFileInfoPerPath(const char* romfs, const char *path, romfs_fileInfo* out); - -#ifdef __cplusplus -} -#endif - diff --git a/src/romfs_helper.cpp b/src/romfs_helper.cpp new file mode 100644 index 0000000..7886932 --- /dev/null +++ b/src/romfs_helper.cpp @@ -0,0 +1,88 @@ +#include "romfs_helper.h" +#include "utils/logger.h" +#include "utils/StringTools.h" +#include +#include + +FileInfos gFileInfos[FILE_INFO_SIZE] __attribute__((section(".data"))); + +void unmountRomfs(uint32_t id) { + if(id >= FILE_INFO_SIZE) { + return; + } + if(gFileInfos[id].romfsMounted) { + char romName [10]; + snprintf(romName,10,"%08X", id); + DEBUG_FUNCTION_LINE("Unmounting %s\n", romName); + int res = romfsUnmount(romName); + DEBUG_FUNCTION_LINE("res: %d\n",res); + gFileInfos[id].romfsMounted = false; + } +} + +void unmountAllRomfs() { + for(int i = 0; i < FILE_INFO_SIZE; i++) { + unmountRomfs(i); + } +} + +bool mountRomfs(uint32_t id) { + if(id >= FILE_INFO_SIZE) { + DEBUG_FUNCTION_LINE("HANDLE WAS TOO BIG %d\n", id); + return false; + } + if(!gFileInfos[id].romfsMounted) { + char buffer [256]; + snprintf(buffer,256,"fs:/vol/external01/%s", gFileInfos[id].path); + char romName [10]; + snprintf(romName,10,"%08X", id); + DEBUG_FUNCTION_LINE("Mount %s as %s\n", buffer, romName); + if(romfsMount(romName,buffer) == 0) { + DEBUG_FUNCTION_LINE("Mounted successfully \n"); + gFileInfos[id].romfsMounted = true; + return true; + } else { + DEBUG_FUNCTION_LINE("Mounting failed\n"); + return false; + } + } + return true; +} + + + + +int32_t getRPXInfoForID(uint32_t id, romfs_fileInfo * info) { + if(!mountRomfs(id)) { + return -1; + } + DIR *dir; + struct dirent *entry; + char romName [10]; + snprintf(romName,10,"%08X", id); + + char root[12]; + snprintf(root,12,"%08X:/", id); + + if (!(dir = opendir(root))) { + return -2; + } + bool found = false; + int res = -3; + while ((entry = readdir(dir)) != NULL) { + if(StringTools::EndsWith(entry->d_name, ".rpx")) { + if(romfs_GetFileInfoPerPath(romName, entry->d_name, info) >= 0) { + found = true; + res = 0; + } + break; + } + } + + closedir(dir); + + if(!found) { + return -4; + } + return res; +} diff --git a/src/romfs_helper.h b/src/romfs_helper.h new file mode 100644 index 0000000..b8df57b --- /dev/null +++ b/src/romfs_helper.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include + + + +typedef struct WUT_PACKED FileInfos_ { + char path[256]; + char name[256]; + int32_t source; + bool romfsMounted; + int openedFiles; +} FileInfos; + +#define FILE_INFO_SIZE 300 +extern FileInfos gFileInfos[FILE_INFO_SIZE]; + + + +void unmountAllRomfs(); +void unmountRomfs(uint32_t id); +bool mountRomfs(uint32_t id); + +int32_t getRPXInfoForID(uint32_t id, romfs_fileInfo * info); diff --git a/src/utils/StringTools.cpp b/src/utils/StringTools.cpp index 7144cfa..ec7cf68 100644 --- a/src/utils/StringTools.cpp +++ b/src/utils/StringTools.cpp @@ -209,3 +209,82 @@ std::vector StringTools::stringSplit(const std::string & inValue, c } return result; } + + +const char * StringTools::FullpathToFilename(const char *path) { + if(!path) + return path; + + const char * ptr = path; + const char * Filename = ptr; + + while(*ptr != '\0') { + if(ptr[0] == '/' && ptr[1] != '\0') + Filename = ptr+1; + + ++ptr; + } + + return Filename; + } + +void StringTools::RemoveDoubleSlashs(std::string &str) { + uint32_t length = str.size(); + + //! clear path of double slashes + for(uint32_t i = 1; i < length; ++i) { + if(str[i-1] == '/' && str[i] == '/') { + str.erase(i, 1); + i--; + length--; + } + } + } + + +// You must free the result if result is non-NULL. +char * StringTools::str_replace(char *orig, char *rep, char *with) { + char *result; // the return string + char *ins; // the next insert point + char *tmp; // varies + int len_rep; // length of rep (the string to remove) + int len_with; // length of with (the string to replace rep with) + int len_front; // distance between rep and end of last rep + int count; // number of replacements + + // sanity checks and initialization + if (!orig || !rep) + return NULL; + len_rep = strlen(rep); + if (len_rep == 0) + return NULL; // empty rep causes infinite loop during count + if (!with) + with = ""; + len_with = strlen(with); + + // count the number of replacements needed + ins = orig; + for (count = 0; tmp = strstr(ins, rep); ++count) { + ins = tmp + len_rep; + } + + tmp = result = (char*)malloc(strlen(orig) + (len_with - len_rep) * count + 1); + + if (!result) + return NULL; + + // first time through the loop, all the variable are set correctly + // from here on, + // tmp points to the end of the result string + // ins points to the next occurrence of rep in orig + // orig points to the remainder of orig after "end of rep" + while (count--) { + ins = strstr(orig, rep); + len_front = ins - orig; + tmp = strncpy(tmp, orig, len_front) + len_front; + tmp = strcpy(tmp, with) + len_with; + orig += len_front + len_rep; // move to next "end of rep" + } + strcpy(tmp, orig); + return result; +} diff --git a/src/utils/StringTools.h b/src/utils/StringTools.h index 1f0e336..8087a70 100644 --- a/src/utils/StringTools.h +++ b/src/utils/StringTools.h @@ -42,37 +42,9 @@ public: static BOOL char2wchar_t(const char * src, wchar_t * dest); static int32_t strtokcmp(const char * string, const char * compare, const char * separator); static int32_t strextcmp(const char * string, const char * extension, char seperator); - - static const char * FullpathToFilename(const char *path) { - if(!path) - return path; - - const char * ptr = path; - const char * Filename = ptr; - - while(*ptr != '\0') { - if(ptr[0] == '/' && ptr[1] != '\0') - Filename = ptr+1; - - ++ptr; - } - - return Filename; - } - - static void RemoveDoubleSlashs(std::string &str) { - uint32_t length = str.size(); - - //! clear path of double slashes - for(uint32_t i = 1; i < length; ++i) { - if(str[i-1] == '/' && str[i] == '/') { - str.erase(i, 1); - i--; - length--; - } - } - } - + static char *str_replace(char *orig, char *rep, char *with); + static const char * FullpathToFilename(const char *path); + static void RemoveDoubleSlashs(std::string &str); static std::vector stringSplit(const std::string & value, const std::string & splitter); };