From d0e8749aa198b45e1bb674ca573d169ff57646bf Mon Sep 17 00:00:00 2001 From: KentuckyCompass Date: Sat, 15 Dec 2012 03:38:14 -0800 Subject: [PATCH 1/5] replace host0 hack with proper relative path handling (not per thread yet) --- Core/FileSystems/MetaFileSystem.cpp | 183 ++++++++++++++++++++++++++-- 1 file changed, 173 insertions(+), 10 deletions(-) diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index 55895968fc..b29b35cebf 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -18,6 +18,161 @@ #include #include "MetaFileSystem.h" +bool applyPathStringToComponentsVector(std::vector &vector, const std::string &pathString) +{ + size_t len = pathString.length(); + size_t start = 0; + + while (start < len) + { + size_t i = pathString.find('/', start); + if (i == std::string::npos) + i = len; + + if (i > start) + { + std::string component = pathString.substr(start, i - start); + if (component != ".") + { + if (component == "..") + { + if (vector.size() != 0) + { + vector.pop_back(); + } + else + { + // what does the real PSP do for "/../filename"? + WARN_LOG(HLE, "RealPath: .. as first path component: \"%s\"", pathString.c_str()); + } + } + else + { + vector.push_back(component); + } + } + } + + start = i + 1; + } + + return true; +} + +/* + * Changes relative paths to absolute, removes ".", "..", and trailing "/" + * babel (and possibly other games) use "/directoryThatDoesNotExist/../directoryThatExists/filename" + */ +bool RealPath(const std::string ¤tDirectory, const std::string &inPath, std::string &outPath) +{ + size_t inLen = inPath.length(); + if (inLen == 0) + { + ERROR_LOG(HLE, "RealPath: inPath is empty"); + return false; + } + + size_t inColon = inPath.find(':'); + if (inColon + 1 == inLen) + { + WARN_LOG(HLE, "RealPath: inPath is all prefix and no path: \"%s\"", inPath.c_str()); + + outPath = inPath; + return true; + } + + std::string curDirPrefix; + size_t curDirColon = std::string::npos, curDirLen = currentDirectory.length(); + if (curDirLen != 0) + { + curDirColon = currentDirectory.find(':'); + + /*if (curDirColon == std::string::npos) + { + WARN_LOG(HLE, "RealPath: currentDirectory has no prefix: \"%s\"", currentDirectory.c_str()); + } + else if (curDirColon + 1 == curDirLen) + { + WARN_LOG(HLE, "RealPath: currentDirectory is all prefix and no path: \"%s\"", currentDirectory.c_str()); + } + else + { + curDirPrefix = currentDirectory.substr(0, curDirColon + 1); + }*/ + + if (curDirColon < curDirLen - 1) + curDirPrefix = currentDirectory.substr(0, curDirColon + 1); + } + + std::string inPrefix, inAfter; + + if (inColon == std::string::npos) + { + inPrefix = curDirPrefix; + inAfter = inPath; + } + else + { + inPrefix = inPath.substr(0, inColon + 1); + inAfter = inPath.substr(inColon + 1); + } + + std::vector cmpnts; // path components + size_t capacityGuess = inPath.length(); + + if ((inAfter[0] != '/')) + { + if (curDirLen == 0) + { + ERROR_LOG(HLE, "RealPath: inPath \"%s\" is relative, but no current directory is set", inPath.c_str()); + return false; + } + + if (curDirColon == std::string::npos || curDirPrefix.length() == 0) + { + ERROR_LOG(HLE, "RealPath: inPath \"%s\" is relative, but current directory \"%s\" has no prefix", inPath.c_str(), currentDirectory.c_str()); + return false; + } + + if (curDirColon + 1 == curDirLen) + { + ERROR_LOG(HLE, "RealPath: inPath \"%s\" is relative, but current directory \"%s\" is all prefix and no path", inPath.c_str(), currentDirectory.c_str()); + return false; + } + + if (inPrefix != curDirPrefix) + WARN_LOG(HLE, "RealPath: inPath \"%s\" is relative to current directory, but specifies a different prefix than current directory \"%s\"", inPath.c_str(), currentDirectory.c_str()); + + const std::string curDirAfter = currentDirectory.substr(curDirColon + 1); + if (! applyPathStringToComponentsVector(cmpnts, curDirAfter) ) + { + DEBUG_LOG(HLE,"RealPath: currentDirectory is not a valid path: \"%s\"", currentDirectory.c_str()); + return false; + } + capacityGuess += currentDirectory.length(); + } + + if (! applyPathStringToComponentsVector(cmpnts, inAfter) ) + { + DEBUG_LOG(HLE, "RealPath: inPath is not a valid path: \"%s\"", inPath.c_str()); + return false; + } + + outPath.clear(); + outPath.reserve(capacityGuess); + + outPath.append(inPrefix); + + size_t numCmpnts = cmpnts.size(); + for (size_t i = 0; i < numCmpnts; i++) + { + outPath.append(1, '/'); + outPath.append(cmpnts[i]); + } + + return true; +} + IFileSystem *MetaFileSystem::GetHandleOwner(u32 handle) { for (size_t i = 0; i < fileSystems.size(); i++) @@ -31,21 +186,29 @@ IFileSystem *MetaFileSystem::GetHandleOwner(u32 handle) bool MetaFileSystem::MapFilePath(std::string inpath, std::string &outpath, IFileSystem **system) { - // host0 HACK - // need to figure out what to do about xxx:./... paths - is there a current dir per drive? - if (!inpath.compare(0, 8, "host0:./")) - inpath = currentDirectory + inpath.substr(7); + //TODO: implement current directory per thread (NOT per drive) + + DEBUG_LOG(HLE, "MapFilePath: starting with \"%s\"", inpath.c_str()); - for (size_t i = 0; i < fileSystems.size(); i++) + if ( RealPath(currentDirectory, inpath, inpath) ) { - int prefLen = fileSystems[i].prefix.size(); - if (fileSystems[i].prefix == inpath.substr(0,prefLen)) + for (size_t i = 0; i < fileSystems.size(); i++) { - outpath = inpath.substr(prefLen); - *system = fileSystems[i].system; - return true; + size_t prefLen = fileSystems[i].prefix.size(); + if (fileSystems[i].prefix == inpath.substr(0, prefLen)) + { + outpath = inpath.substr(prefLen); + *system = fileSystems[i].system; + + DEBUG_LOG(HLE, "MapFilePath: mapped to prefix: \"%s\", path: \"%s\"", fileSystems[i].prefix.c_str(), outpath.c_str()); + + return true; + } } } + + DEBUG_LOG(HLE, "MapFilePath: failed!!!"); + return false; } From 0639abff6a50a01deaa8f25f6eb4799d3bd551f9 Mon Sep 17 00:00:00 2001 From: KentuckyCompass Date: Sat, 15 Dec 2012 03:47:31 -0800 Subject: [PATCH 2/5] more consistant messages and minor adjustments --- Core/FileSystems/MetaFileSystem.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index b29b35cebf..c35a8f1c8b 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -87,21 +87,23 @@ bool RealPath(const std::string ¤tDirectory, const std::string &inPath, st { curDirColon = currentDirectory.find(':'); - /*if (curDirColon == std::string::npos) +#ifdef _DEBUG + if (curDirColon == std::string::npos) { - WARN_LOG(HLE, "RealPath: currentDirectory has no prefix: \"%s\"", currentDirectory.c_str()); + DEBUG_LOG(HLE, "RealPath: currentDirectory has no prefix: \"%s\"", currentDirectory.c_str()); } else if (curDirColon + 1 == curDirLen) { - WARN_LOG(HLE, "RealPath: currentDirectory is all prefix and no path: \"%s\"", currentDirectory.c_str()); + DEBUG_LOG(HLE, "RealPath: currentDirectory is all prefix and no path: \"%s\"", currentDirectory.c_str()); } else { curDirPrefix = currentDirectory.substr(0, curDirColon + 1); - }*/ - + } +#else if (curDirColon < curDirLen - 1) curDirPrefix = currentDirectory.substr(0, curDirColon + 1); +#endif } std::string inPrefix, inAfter; @@ -124,7 +126,7 @@ bool RealPath(const std::string ¤tDirectory, const std::string &inPath, st { if (curDirLen == 0) { - ERROR_LOG(HLE, "RealPath: inPath \"%s\" is relative, but no current directory is set", inPath.c_str()); + ERROR_LOG(HLE, "RealPath: inPath \"%s\" is relative, but current directory is empty", inPath.c_str()); return false; } @@ -141,7 +143,7 @@ bool RealPath(const std::string ¤tDirectory, const std::string &inPath, st } if (inPrefix != curDirPrefix) - WARN_LOG(HLE, "RealPath: inPath \"%s\" is relative to current directory, but specifies a different prefix than current directory \"%s\"", inPath.c_str(), currentDirectory.c_str()); + WARN_LOG(HLE, "RealPath: inPath \"%s\" is relative, but specifies a different prefix than current directory \"%s\"", inPath.c_str(), currentDirectory.c_str()); const std::string curDirAfter = currentDirectory.substr(curDirColon + 1); if (! applyPathStringToComponentsVector(cmpnts, curDirAfter) ) @@ -149,6 +151,7 @@ bool RealPath(const std::string ¤tDirectory, const std::string &inPath, st DEBUG_LOG(HLE,"RealPath: currentDirectory is not a valid path: \"%s\"", currentDirectory.c_str()); return false; } + capacityGuess += currentDirectory.length(); } From 17d7e4acf58679945123151636ef6223115ef29d Mon Sep 17 00:00:00 2001 From: KentuckyCompass Date: Sat, 15 Dec 2012 03:48:47 -0800 Subject: [PATCH 3/5] invalid current directory should be ERROR_LOG --- Core/FileSystems/MetaFileSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index c35a8f1c8b..37e226dee1 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -148,7 +148,7 @@ bool RealPath(const std::string ¤tDirectory, const std::string &inPath, st const std::string curDirAfter = currentDirectory.substr(curDirColon + 1); if (! applyPathStringToComponentsVector(cmpnts, curDirAfter) ) { - DEBUG_LOG(HLE,"RealPath: currentDirectory is not a valid path: \"%s\"", currentDirectory.c_str()); + ERROR_LOG(HLE,"RealPath: currentDirectory is not a valid path: \"%s\"", currentDirectory.c_str()); return false; } From 8f00757ceb448033f1839ec3fed8bf12c2a8c8ff Mon Sep 17 00:00:00 2001 From: KentuckyCompass Date: Sat, 15 Dec 2012 03:55:02 -0800 Subject: [PATCH 4/5] remove simple current directory concatenation in favor of new relative path handling --- Core/FileSystems/MetaFileSystem.cpp | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index 37e226dee1..6351bc0522 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -246,11 +246,6 @@ void MetaFileSystem::UnmountAll() u32 MetaFileSystem::OpenFile(std::string filename, FileAccess access) { std::string of; - if (filename.find(':') == std::string::npos) - { - filename = currentDirectory + "/" + filename; - DEBUG_LOG(HLE,"OpenFile: Expanded path to %s", filename.c_str()); - } IFileSystem *system; if (MapFilePath(filename, of, &system)) { @@ -265,11 +260,6 @@ u32 MetaFileSystem::OpenFile(std::string filename, FileAccess access) PSPFileInfo MetaFileSystem::GetFileInfo(std::string filename) { std::string of; - if (filename.find(':') == std::string::npos) - { - filename = currentDirectory + "/" + filename; - DEBUG_LOG(HLE,"GetFileInfo: Expanded path to %s", filename.c_str()); - } IFileSystem *system; if (MapFilePath(filename, of, &system)) { @@ -295,14 +285,6 @@ bool stringEndsWith (std::string const &fullString, std::string const &ending) std::vector MetaFileSystem::GetDirListing(std::string path) { std::string of; - if (path.find(':') == std::string::npos) - { - if (!stringEndsWith(currentDirectory, "/")) - { - path = currentDirectory + "/" + path; - } - DEBUG_LOG(HLE,"GetFileInfo: Expanded path to %s", path.c_str()); - } IFileSystem *system; if (MapFilePath(path, of, &system)) { From 360738d36645db3594d734db52ec12ec3b7ce613 Mon Sep 17 00:00:00 2001 From: KentuckyCompass Date: Sat, 15 Dec 2012 04:09:37 -0800 Subject: [PATCH 5/5] tolerate prefix without path in current directory and quiet redundant 'starting with' message --- Core/FileSystems/MetaFileSystem.cpp | 39 +++++++++++++---------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index 6351bc0522..b1b48ba11d 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -87,23 +87,17 @@ bool RealPath(const std::string ¤tDirectory, const std::string &inPath, st { curDirColon = currentDirectory.find(':'); -#ifdef _DEBUG if (curDirColon == std::string::npos) { DEBUG_LOG(HLE, "RealPath: currentDirectory has no prefix: \"%s\"", currentDirectory.c_str()); } - else if (curDirColon + 1 == curDirLen) - { - DEBUG_LOG(HLE, "RealPath: currentDirectory is all prefix and no path: \"%s\"", currentDirectory.c_str()); - } else { + if (curDirColon + 1 == curDirLen) + DEBUG_LOG(HLE, "RealPath: currentDirectory is all prefix and no path: \"%s\"", currentDirectory.c_str()); + curDirPrefix = currentDirectory.substr(0, curDirColon + 1); } -#else - if (curDirColon < curDirLen - 1) - curDirPrefix = currentDirectory.substr(0, curDirColon + 1); -#endif } std::string inPrefix, inAfter; @@ -136,20 +130,21 @@ bool RealPath(const std::string ¤tDirectory, const std::string &inPath, st return false; } - if (curDirColon + 1 == curDirLen) - { - ERROR_LOG(HLE, "RealPath: inPath \"%s\" is relative, but current directory \"%s\" is all prefix and no path", inPath.c_str(), currentDirectory.c_str()); - return false; - } - if (inPrefix != curDirPrefix) WARN_LOG(HLE, "RealPath: inPath \"%s\" is relative, but specifies a different prefix than current directory \"%s\"", inPath.c_str(), currentDirectory.c_str()); - - const std::string curDirAfter = currentDirectory.substr(curDirColon + 1); - if (! applyPathStringToComponentsVector(cmpnts, curDirAfter) ) + + if (curDirColon + 1 == curDirLen) { - ERROR_LOG(HLE,"RealPath: currentDirectory is not a valid path: \"%s\"", currentDirectory.c_str()); - return false; + ERROR_LOG(HLE, "RealPath: inPath \"%s\" is relative, but current directory \"%s\" is all prefix and no path. Using \"/\" as path for current directory.", inPath.c_str(), currentDirectory.c_str()); + } + else + { + const std::string curDirAfter = currentDirectory.substr(curDirColon + 1); + if (! applyPathStringToComponentsVector(cmpnts, curDirAfter) ) + { + ERROR_LOG(HLE,"RealPath: currentDirectory is not a valid path: \"%s\"", currentDirectory.c_str()); + return false; + } } capacityGuess += currentDirectory.length(); @@ -191,7 +186,7 @@ bool MetaFileSystem::MapFilePath(std::string inpath, std::string &outpath, IFile { //TODO: implement current directory per thread (NOT per drive) - DEBUG_LOG(HLE, "MapFilePath: starting with \"%s\"", inpath.c_str()); + //DEBUG_LOG(HLE, "MapFilePath: starting with \"%s\"", inpath.c_str()); if ( RealPath(currentDirectory, inpath, inpath) ) { @@ -210,7 +205,7 @@ bool MetaFileSystem::MapFilePath(std::string inpath, std::string &outpath, IFile } } - DEBUG_LOG(HLE, "MapFilePath: failed!!!"); + DEBUG_LOG(HLE, "MapFilePath: failed, returning false"); return false; }