// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - POSIXFilesystemNode::POSIXFilesystemNode(const string& p, bool verify) { // Expand '~/' and './' to the value of the HOME env variable if ( p.length() >= 2 && (p[0] == '~' || p[0] == '.') && p[1] == '/') { const char *home = getenv("HOME"); #ifdef MAXPATHLEN if (home != NULL && strlen(home) < MAXPATHLEN) #else // No MAXPATHLEN, as happens on Hurd if (home != NULL) #endif { _path = home; // Skip over the tilde/dot. We know that p contains at least // two chars, so this is safe: _path += p.c_str() + 1; } } else _path = p; _displayName = lastPathComponent(_path); if (verify) { setFlags(); // Add a trailing slash, if necessary if (_isDirectory && _path.length() > 0 && _path[_path.length()-1] != '/') _path += '/'; } }
WindowsFilesystemNode::WindowsFilesystemNode(const Common::String &p, const bool currentDir) { if (currentDir) { char path[MAX_PATH]; GetCurrentDirectory(MAX_PATH, path); _path = path; } else { assert(p.size() > 0); _path = p; } _displayName = lastPathComponent(_path, '\\'); // Check whether it is a directory, and whether the file actually exists DWORD fileAttribs = GetFileAttributes(toUnicode(_path.c_str())); if (fileAttribs == INVALID_FILE_ATTRIBUTES) { _isDirectory = false; _isValid = false; } else { _isDirectory = ((fileAttribs & FILE_ATTRIBUTE_DIRECTORY) != 0); _isValid = true; // Add a trailing slash, if necessary. if (_isDirectory && _path.lastChar() != '\\') { _path += '\\'; } } _isPseudoRoot = false; }
static byte *readSavegameThumbnail(const Common::String &filename, uint &fileSize, bool &isPNG) { byte *pFileData; Common::SaveFileManager *sfm = g_system->getSavefileManager(); Common::InSaveFile *file = sfm->openForLoading(lastPathComponent(filename, '/')); if (!file) error("Save file \"%s\" could not be loaded.", filename.c_str()); // Seek to the actual PNG image loadString(*file); // Marker (BS25SAVEGAME) Common::String storedVersionID = loadString(*file); // Version if (storedVersionID != "SCUMMVM1") loadString(*file); loadString(*file); // Description uint32 compressedGamedataSize = atoi(loadString(*file).c_str()); loadString(*file); // Uncompressed game data size file->skip(compressedGamedataSize); // Skip the game data and move to the thumbnail itself uint32 thumbnailStart = file->pos(); fileSize = file->size() - thumbnailStart; // Check if the thumbnail is in our own format, or a PNG file. uint32 header = file->readUint32BE(); isPNG = (header != MKTAG('S','C','R','N')); file->seek(-4, SEEK_CUR); pFileData = new byte[fileSize]; file->read(pFileData, fileSize); delete file; return pFileData; }
AbstractFilesystemNode *WindowsFilesystemNode::parent() const { assert(_isValid || _isPseudoRoot); if (_isPseudoRoot) return 0; WindowsFilesystemNode *p = new WindowsFilesystemNode(); if (_path.size() > 3) { const char *start = _path.c_str(); const char *end = lastPathComponent(_path); p = new WindowsFilesystemNode(); p->_path = String(start, end - start); p->_isValid = true; p->_isDirectory = true; p->_displayName = lastPathComponent(p->_path); p->_isPseudoRoot = false; } return p; }
AbstractFSNode *RoninCDFileNode::getParent() const { if (_path == "/") return 0; const char *start = _path.c_str(); const char *end = lastPathComponent(_path, '/'); return new RoninCDDirectoryNode(Common::String(start, end - start)); }
AbstractFSNode *WiiFilesystemNode::getParent() const { if (_path.empty()) return NULL; const char *start = _path.c_str(); const char *end = lastPathComponent(_path, '/'); return new WiiFilesystemNode(Common::String(start, end - start)); }
AbstractFSNode *N64FilesystemNode::getParent() const { if (_path == ROOT_PATH) return 0; const char *start = _path.c_str(); const char *end = lastPathComponent(_path, '/'); return new N64FilesystemNode(Common::String(start, end - start), false); }
AbstractFilesystemNode *GP32FilesystemNode::parent() const { if(_isRoot) return 0; GP32FilesystemNode *p = new GP32FilesystemNode(); if (_path.size() > 4) { const char *start = _path.c_str(); const char *end = lastPathComponent(_path); p->_path = String(start, end - start); p->_isDirectory = true; p->_displayName = lastPathComponent(p->_path); p->_isRoot = false; GPDEBUG("%s", p->_path.c_str()); } return p; }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AbstractFilesystemNode* POSIXFilesystemNode::getParent() const { if (_path == "/") return 0; const char *start = _path.c_str(); const char *end = lastPathComponent(_path); return new POSIXFilesystemNode(string(start, end - start), true); }
AbstractFSNode *PSPFilesystemNode::getParent() const { DEBUG_ENTER_FUNC(); if (_path == ROOT_PATH) return 0; PSP_DEBUG_PRINT_FUNC("current[%s]\n", _path.c_str()); const char *start = _path.c_str(); const char *end = lastPathComponent(_path, '/'); AbstractFSNode *node = new PSPFilesystemNode(Common::String(start, end - start), false); return node; }
N64FilesystemNode::N64FilesystemNode(const Common::String &p, bool verify) { assert(p.size() > 0); _path = p; _displayName = lastPathComponent(_path, '/'); _isValid = true; _isDirectory = true; // Check if it's a dir ROMFILE *tmpfd = romfs_open(p.c_str(), "r"); if (tmpfd) { _isDirectory = (tmpfd->type == 0 || tmpfd->type == 1); romfs_close(tmpfd); } }
WiiFilesystemNode::WiiFilesystemNode(const Common::String &p, const struct stat *st) { if (p.empty()) { initRootNode(); return; } _path = Common::normalizePath(p, '/'); // "sd:" is not a valid directory, but "sd:/" is if (_path.lastChar() == ':') _path += '/'; _displayName = lastPathComponent(_path, '/'); setFlags(st); }
WindowsFilesystemNode::WindowsFilesystemNode(const String &p) { assert(p.size() > 0); _path = p; _displayName = lastPathComponent(_path); // Check whether it is a directory, and whether the file actually exists DWORD fileAttribs = GetFileAttributes(toUnicode(_path.c_str())); if (fileAttribs == INVALID_FILE_ATTRIBUTES) { _isValid = false; _isDirectory = false; } else { _isValid = true; _isDirectory = ((fileAttribs & FILE_ATTRIBUTE_DIRECTORY) != 0); } _isPseudoRoot = false; }
WindowsFilesystemNode::WindowsFilesystemNode(const Common::String &p, const bool currentDir) { if (currentDir) { char path[MAX_PATH]; GetCurrentDirectory(MAX_PATH, path); _path = path; } else { assert(p.size() > 0); #ifndef _WIN32_WCE _path = p; #else // Check whether p is a relative path if (p.hasPrefix("\\") || p.hasPrefix("/")) { _path = p; } else { // Add current directory as a prefix to the path // (Windows CE has no concept for relative paths) char path[MAX_PATH]; GetCurrentDirectory(MAX_PATH, path); _path = path; _path += '\\'; _path += p; } #endif } _displayName = lastPathComponent(_path, '\\'); // Check whether it is a directory, and whether the file actually exists DWORD fileAttribs = GetFileAttributes(toUnicode(_path.c_str())); if (fileAttribs == INVALID_FILE_ATTRIBUTES) { _isDirectory = false; _isValid = false; } else { _isDirectory = ((fileAttribs & FILE_ATTRIBUTE_DIRECTORY) != 0); _isValid = true; // Add a trailing slash, if necessary. if (_isDirectory && _path.lastChar() != '\\') { _path += '\\'; } } _isPseudoRoot = false; }
PSPFilesystemNode::PSPFilesystemNode(const Common::String &p, bool verify) { DEBUG_ENTER_FUNC(); assert(p.size() > 0); _path = p; _displayName = lastPathComponent(_path, '/'); _isValid = true; _isDirectory = true; PSP_DEBUG_PRINT_FUNC("path [%s]\n", _path.c_str()); if (verify) { struct stat st; if (PowerMan.beginCriticalSection() == PowerManager::Blocked) PSP_DEBUG_PRINT_FUNC("Suspended\n"); _isValid = (0 == stat(_path.c_str(), &st)); PowerMan.endCriticalSection(); _isDirectory = S_ISDIR(st.st_mode); } }
WiiFilesystemNode::WiiFilesystemNode(const Common::String &p) { if (p.empty()) { initRootNode(); return; } _path = Common::normalizePath(p, '/'); WiiFilesystemFactory::instance().mountByPath(_path); // "sd:" is not a valid directory, but "sd:/" is if (_path.lastChar() == ':') _path += '/'; _displayName = lastPathComponent(_path, '/'); struct stat st; if(stat(_path.c_str(), &st) != -1) setFlags(&st); else clearFlags(); }
int main (int argc, char **argv) { // start flags declarations... gDataOffset = 0; //globally declared in GCMutils.h; Must be initialized before use... int hexFlag = 0; //for extracting: char *extractFileFrom = NULL; char *extractFileTo = NULL; char *fsReplacePath = NULL; verboseFlag = 0; int showInfoFlag = 1; int extractDiskHeaderFlag = 0; char *extractDiskHeaderFile = GCM_DISK_HEADER_FILENAME; int extractDiskHeaderInfoFlag = 0; char *extractDiskHeaderInfoFile = GCM_DISK_HEADER_INFO_FILENAME; int extractApploaderFlag = 0; char *extractApploaderFile = GCM_APPLOADER_FILENAME; int extractBootDolFlag = 0; char *extractBootDolFile = GCM_BOOT_DOL_FILENAME; int injectDiskHeaderFlag = 0; char *injectDiskHeaderFile = GCM_DISK_HEADER_FILENAME; int injectDiskHeaderInfoFlag = 0; char *injectDiskHeaderInfoFile = GCM_DISK_HEADER_INFO_FILENAME; int injectApploaderFlag = 0; char *injectApploaderFile = GCM_APPLOADER_FILENAME; char *replaceFileLocalPath = NULL; char *replaceFileGCMPath = NULL; int listFilesFlag = 0; listInfoFlag = 0; listPathFlag = 0; // end flag declarations //start argument parsing... char *currentArg = NULL; do { currentArg = GET_NEXT_ARG; if (!currentArg) { //there's no args! uh oh! //printf("No arguments...\n"); printUsage(); exit(0); } else if (CHECK_ARG(ARG_VERBOSE)) { //turn on verbosity! verboseFlag++; verbosePrint("Verbose output ON."); } else if (CHECK_ARG(ARG_HELP)) { // print extended help printExtendedUsage(); exit(0); } else if (CHECK_ARG(ARG_INFO)) { //they want to see info... showInfoFlag++; verbosePrint("Show info flag ON."); } else if (CHECK_ARG(ARG_HEX)) { //they want hex notation... hexFlag = 1; verbosePrint("Hex notation ON."); } else if (CHECK_ARG(ARG_OFFSET)) { //change the data offset gDataOffset = strtoul(GET_NEXT_ARG, NULL, 0); char verboseMsg[32] = ""; sprintf(verboseMsg, "Data offset changed to: %d", gDataOffset); verbosePrint(verboseMsg); } else if (CHECK_ARG(ARG_REPLACE_FILESYSTEM)) { // they want to replace the filesystem fsReplacePath = GET_NEXT_ARG; if (!fsReplacePath) { printf("Argument error...\n"); printUsage(); exit(1); } } else if (CHECK_ARG(ARG_EXTRACT)) { // extract files... // usage: -e <path> <destPath> extractFileFrom = GET_NEXT_ARG; extractFileTo = GET_NEXT_ARG; if (!extractFileFrom || !extractFileTo) { //argument error... something was omitted... printf("Argument error.\n"); printUsage(); exit(1); } } else if (CHECK_ARG(ARG_EXTRACT_DISK_HEADER)) { // extract disk header... (to a file called "boot.bin") extractDiskHeaderFlag++; if (PEEK_ARG && strcmp(PEEK_ARG, OPT_FILE) == 0) { // if they're specifying a file... SKIP_NARG(1); //skip that -f we just looked at... extractDiskHeaderFile = GET_NEXT_ARG; } } else if (CHECK_ARG(ARG_EXTRACT_DISK_HEADER_INFO)) { // extract disk header info... (to a file called "bi2.bin") extractDiskHeaderInfoFlag++; if (PEEK_ARG && strcmp(PEEK_ARG, OPT_FILE) == 0) { // if they're specifying a file... SKIP_NARG(1); //skip that -f we just looked at... extractDiskHeaderInfoFile = GET_NEXT_ARG; } } else if (CHECK_ARG(ARG_EXTRACT_APPLOADER)) { //extract apploader... (to a file called "appldr.bin") extractApploaderFlag++; if (PEEK_ARG && strcmp(PEEK_ARG, OPT_FILE) == 0) { // if they're specifying a file... SKIP_NARG(1); //skip that -f we just looked at... extractApploaderFile = GET_NEXT_ARG; } } else if (CHECK_ARG(ARG_EXTRACT_BOOT_DOL)) { //extract the boot dol... extractBootDolFlag++; if (PEEK_ARG && strcmp(PEEK_ARG, OPT_FILE) == 0) { //if they specify a file... SKIP_NARG(1); //skip that -f extractBootDolFile = GET_NEXT_ARG; } } else if (CHECK_ARG(ARG_INJECT_DISK_HEADER)) { //inject the diskheader injectDiskHeaderFlag++; if (PEEK_ARG && strcmp(PEEK_ARG, OPT_FILE) == 0) { //if they're specifying a file... (otherwise use the default); SKIP_NARG(1); //skip the -f we just looked at... injectDiskHeaderFile = GET_NEXT_ARG; } } else if (CHECK_ARG(ARG_INJECT_DISK_HEADER_INFO)) { //inject the diskheaderinfo... injectDiskHeaderInfoFlag++; if (PEEK_ARG && strcmp(PEEK_ARG, OPT_FILE) == 0) { // if they're specifying a file... SKIP_NARG(1); injectDiskHeaderInfoFile = GET_NEXT_ARG; } } else if (CHECK_ARG(ARG_INJECT_APPLOADER)) { //inject the apploader... injectApploaderFlag++; if (PEEK_ARG && strcmp(PEEK_ARG, OPT_FILE) == 0) { //if they're specifying a file... SKIP_NARG(1); injectApploaderFile = GET_NEXT_ARG; } } else if (CHECK_ARG(ARG_REPLACE_FILE)) { //they want to replace a file... replaceFileGCMPath = GET_NEXT_ARG; replaceFileLocalPath = GET_NEXT_ARG; if (!replaceFileGCMPath || !replaceFileLocalPath) { printf("Argument error!\n"); printUsage(); exit(1); } } else if (CHECK_ARG(ARG_LIST)) { // list filesystem listFilesFlag++; //turn the listFiles flag on. while(1) { if (PEEK_ARG && (strcmp(PEEK_ARG, OPT_FILE_INFO) == 0 || strcmp(PEEK_ARG, OPT_FILE_INFO_SYN) == 0)) { SKIP_NARG(1); listInfoFlag++; } else if (PEEK_ARG && (strcmp(PEEK_ARG, OPT_FULL_PATH) == 0 || strcmp(PEEK_ARG, OPT_FULL_PATH_SYN) == 0)) { SKIP_NARG(1); listPathFlag++; } else { break; } } } else { // do it to this file... this is the last argument... just ignore the rest... filepath = currentArg; filename = lastPathComponent(filepath); break; } } while(*argv); //end parsing arguments... //open the file for reading and start doing read operations! openFile("r"); // print the info... if (showInfoFlag) { printGCMInfo(hexFlag); } // list the files, if necesary... if (listFilesFlag) { listFiles(); } // extract files... if (extractFileFrom && extractFileTo) { //testing recursive extraction... GCMFileEntryStruct *e = NULL; if (strcmp(extractFileFrom, "/") == 0) { e = GCMGetRootFileEntry(gcmFile); printf("root file entry index: %d\n", e->index); } else { e = GCMGetFileEntryAtPath(gcmFile, extractFileFrom); } strcpy(extractRootPath, extractFileTo); recurseFileEntry(e, extractFileEntry); free(e); //extractFile(extractFileFrom, extractFileTo); } //extract diskheader if (extractDiskHeaderFlag) { extractDiskHeader(extractDiskHeaderFile); } //extract diskheaderinfo if (extractDiskHeaderInfoFlag) { extractDiskHeaderInfo(extractDiskHeaderInfoFile); } //extract apploader if (extractApploaderFlag) { extractApploader(extractApploaderFile); } //extract main executable DOL if (extractBootDolFlag) { extractBootDol(extractBootDolFile); } //close the file and open it again for read/write closeFile(); openFile("r+"); //inject the diskheader if (injectDiskHeaderFlag) { injectDiskHeader(injectDiskHeaderFile); } //inject the diskheaderinfo if (injectDiskHeaderInfoFlag) { injectDiskHeaderInfo(injectDiskHeaderInfoFile); } //inject the apploader if (injectApploaderFlag) { injectApploader(injectApploaderFile); } if (replaceFileLocalPath && replaceFileGCMPath) { replaceFile(replaceFileGCMPath, replaceFileLocalPath); } //replace the filesystem if (fsReplacePath) { GCMReplaceFilesystem(gcmFile, fsReplacePath); } closeFile(); return 0; }
virtual Common::String getName() const { return lastPathComponent(_path, '/'); }
int main(int argc, char **argv) { verboseFlag = 0; char *currentArg = NULL; do { currentArg = GET_NEXT_ARG; if (!currentArg) { //there's no args! uh oh! printUsage(); exit(EXIT_SUCCESS); //exit success because we're just printing usage... } else if (CHECK_ARG(ARG_VERBOSE)) { //turn on verbosity! verboseFlag++; // verbosePrint("Verbose output ON."); } else { //this is the file we want to open... filepath = currentArg; filename = lastPathComponent(filepath); break; } } while(*argv); printf("opening %s\n", filename); FILE *gcmFile; if (!(gcmFile = fopen(filepath, "r"))) { perror("error opening!\n"); exit(EXIT_FAILURE); } u32 fstOffset = GCMGetFSTOffset(gcmFile); u32 fstSize = GCMGetFSTSize(gcmFile); u32 stringTableOffset = GCMGetStringTableOffset(gcmFile); GCMFileEntryStruct *root = GCMGetRootFileEntry(gcmFile); u32 filesize = GetFilesizeFromStream(gcmFile); printf("Filesize: %ld\n", filesize); printf("FST Offset: %ld\n", fstOffset); printf("FST Size: %ld\n", fstSize); printf("String Table: %ld\n", stringTableOffset); printf("entry count: %ld\n", root->length); int i = 0; u32 highestStringTableOffset = 0; u32 firstFileOffset = GetFilesizeFromStream(gcmFile); u32 endOfFileList = 0; for (i = 0; i < root->length; i++) { GCMFileEntryStruct *e = GCMGetNthFileEntry(gcmFile, i); GCMFetchFilenameForFileEntry(gcmFile, e); printf("%s\n", e->filename); if (e->filenameOffset >= highestStringTableOffset) { highestStringTableOffset = e->filenameOffset + strlen(e->filename) + 1; // +1 for \0 } if (!(e->isDir) && e->offset < firstFileOffset) { firstFileOffset = e->offset; } if (!(e->isDir) && e->offset + e->length > endOfFileList) { endOfFileList = (e->offset + e->length); } } printf("\n"); printf("HighestStringTableOffset: %ld\n", highestStringTableOffset); printf("firstFileOffset: %ld\n", firstFileOffset); printf("endOfFileList: %ld\n", endOfFileList); printf("\n"); printf("Savings: %ld\n", firstFileOffset - (stringTableOffset + highestStringTableOffset)); printf("Verifying...\n"); fseek(gcmFile, stringTableOffset + highestStringTableOffset, SEEK_SET); while (!fgetc(gcmFile)); printf("currentOffset: %ld\n", ftell(gcmFile)); if (ftell(gcmFile) >= firstFileOffset) { printf("Everything seems ok... YAY!\n"); } else { printf("EEK! no good! something's wrong.\n"); } fclose(gcmFile); }