diff --git a/Utilities/rFile.cpp b/Utilities/rFile.cpp index c0257fbed7..345aa284c5 100644 --- a/Utilities/rFile.cpp +++ b/Utilities/rFile.cpp @@ -15,6 +15,125 @@ std::wstring ConvertUTF8ToWString(const std::string &source) { } #endif +bool getFileInfo(const char *path, FileInfo *fileInfo) { + // TODO: Expand relative paths? + fileInfo->fullName = path; + +#ifdef _WIN32 + WIN32_FILE_ATTRIBUTE_DATA attrs; + if (!GetFileAttributesExW(ConvertUTF8ToWString(path).c_str(), GetFileExInfoStandard, &attrs)) { + fileInfo->size = 0; + fileInfo->isDirectory = false; + fileInfo->exists = false; + return false; + } + fileInfo->size = (uint64_t)attrs.nFileSizeLow | ((uint64_t)attrs.nFileSizeHigh << 32); + fileInfo->isDirectory = (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; + fileInfo->isWritable = (attrs.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0; + fileInfo->exists = true; +#else + struct stat64 file_info; + int result = stat64(path, &file_info); + + if (result < 0) { + LOG_NOTICE(GENERAL, "IsDirectory: stat failed on %s", path); + fileInfo->exists = false; + return false; + } + + fileInfo->isDirectory = S_ISDIR(file_info.st_mode); + fileInfo->isWritable = false; + fileInfo->size = file_info.st_size; + fileInfo->exists = true; + // HACK: approximation + if (file_info.st_mode & 0200) + fileInfo->isWritable = true; +#endif + return true; +} + +bool rIsDir(const std::string &filename) { + FileInfo info; + getFileInfo(filename.c_str(), &info); + return info.isDirectory; +} + +bool rMkdir(const std::string &dir) +{ + return !mkdir(dir.c_str()); +} + +bool rMkpath(const std::string &path) +{ + size_t start=0, pos; + std::string dir; + bool ret; + + while (true) { + if ((pos = path.find_first_of('/', start)) == std::string::npos) + pos = path.length(); + + dir = path.substr(0,pos++); + start = pos; + if(dir.size() == 0) + continue; + if((ret = mkdir(dir.c_str())) && errno != EEXIST){ + return !ret; + } + if (pos == path.length()) + return true; + } + return true; +} + +bool rRmdir(const std::string &dir) +{ +#ifdef _WIN32 + if (!RemoveDirectory(ConvertUTF8ToWString(dir).c_str())) { + LOG_ERROR(GENERAL, "Error deleting directory %s: %i", dir.c_str(), GetLastError()); + return false; + } + return true; +#else + rmdir(dir.c_str()); +#endif +} + +bool rRename(const std::string &from, const std::string &to) +{ + // TODO: Deal with case-sensitivity +#ifdef _WIN32 + return (MoveFile(ConvertUTF8ToWString(from).c_str(), ConvertUTF8ToWString(to).c_str()) == TRUE); +#else + return (0 == rename(from.c_str(), to.c_str())); +#endif +} + +bool rExists(const std::string &file) +{ +#ifdef _WIN32 + std::wstring wstr = ConvertUTF8ToWString(file); + return GetFileAttributes(wstr.c_str()) != 0xFFFFFFFF; +#else + struct stat buffer; + return (stat (file.c_str(), &buffer) == 0); +#endif +} + +bool rRemoveFile(const std::string &file) +{ +#ifdef _WIN32 + if (!DeleteFile(ConvertUTF8ToWString(file).c_str())) { + LOG_ERROR(GENERAL, "Error deleting %s: %i", file.c_str(), GetLastError()); + } +#else + int err = unlink(file.c_str()); + if (err) { + LOG_ERROR(GENERAL, "Error unlinking %s: %i", file.c_str(), err); + } +#endif +} + wxFile::OpenMode convertOpenMode(rFile::OpenMode open) { wxFile::OpenMode mode; @@ -143,7 +262,7 @@ bool rFile::Close() bool rFile::Create(const std::string &filename, bool overwrite, int access) { - return reinterpret_cast(handle)->Create(fmt::FromUTF8(filename),overwrite,access); + return reinterpret_cast(handle)->Create(fmt::FromUTF8(filename), overwrite, access); } bool rFile::Open(const std::string &filename, rFile::OpenMode mode, int access) @@ -151,11 +270,6 @@ bool rFile::Open(const std::string &filename, rFile::OpenMode mode, int access) return reinterpret_cast(handle)->Open(fmt::FromUTF8(filename), convertOpenMode(mode), access); } -bool rFile::Exists(const std::string &file) -{ - return rExists(file); -} - bool rFile::IsOpened() const { return reinterpret_cast(handle)->IsOpened(); @@ -181,85 +295,6 @@ size_t rFile::Tell() const return reinterpret_cast(handle)->Tell(); } -std::string rGetCwd() -{ - return fmt::ToUTF8(wxGetCwd()); -} - -bool rMkdir(const std::string &dir) -{ - return !mkdir(dir.c_str()); -} - -bool rMkpath(const std::string& path) -{ - return wxFileName::Mkdir(fmt::FromUTF8(path), 0777, wxPATH_MKDIR_FULL); -} - -bool rRmdir(const std::string &dir) -{ -#ifdef _WIN32 - if (!RemoveDirectory(ConvertUTF8ToWString(dir).c_str())) { - LOG_ERROR(GENERAL, "Error deleting directory %s: %i", dir, GetLastError()); - return false; - } - return true; -#else - rmdir(dir.c_str()); -#endif -} - -bool rRename(const std::string &from, const std::string &to) -{ - // TODO: Deal with case-sensitivity -#ifdef _WIN32 - return (MoveFile(ConvertUTF8ToWString(from).c_str(), ConvertUTF8ToWString(to).c_str()) == TRUE); -#else - return (0 == rename(from.c_str(), to.c_str())); -#endif -} - -bool rExists(const std::string &file) -{ -#ifdef _WIN32 - std::wstring wstr = ConvertUTF8ToWString(file); - return GetFileAttributes(wstr.c_str()) != 0xFFFFFFFF; -#else - struct stat buffer; - return (stat (file.c_str(), &buffer) == 0); -#endif -} - -bool rDirExists(const std::string &path) -{ - return wxDirExists(fmt::FromUTF8(path)); -} - -bool rFileExists(const std::string &path) -{ - return wxFileExists(fmt::FromUTF8(path)); -} - -bool rRemoveFile(const std::string &path) -{ - return wxRemoveFile(fmt::FromUTF8(path)); -} - -bool rIsWritable(const std::string& path) -{ - return wxIsWritable(fmt::FromUTF8(path)); -} - -bool rIsReadable(const std::string& path) -{ - return wxIsReadable(fmt::FromUTF8(path)); -} - -bool rIsExecutable(const std::string& path) -{ - return wxIsExecutable(fmt::FromUTF8(path)); -} - rDir::rDir() { handle = reinterpret_cast(new wxDir()); @@ -280,11 +315,6 @@ bool rDir::Open(const std::string& path) return reinterpret_cast(handle)->Open(fmt::FromUTF8(path)); } -bool rDir::Exists(const std::string &path) -{ - return rFile::Exists(path); -} - bool rDir::GetFirst(std::string *filename) const { wxString str; diff --git a/Utilities/rFile.h b/Utilities/rFile.h index 55a760abef..fb2be71fbb 100644 --- a/Utilities/rFile.h +++ b/Utilities/rFile.h @@ -2,6 +2,24 @@ #include +struct FileInfo { + std::string name; + std::string fullName; + bool exists; + bool isDirectory; + bool isWritable; + uint64_t size; +}; + +bool getFileInfo(const char *path, FileInfo *fileInfo); +bool rIsDir(const std::string& filename); +bool rRmdir(const std::string& dir); +bool rMkdir(const std::string& dir); +bool rMkpath(const std::string& path); +bool rRename(const std::string &from, const std::string &to); +bool rExists(const std::string &path); +bool rRemoveFile(const std::string &path); + enum rSeekMode { rFromStart, @@ -41,20 +59,6 @@ public: void *handle; }; -std::string rGetCwd(); -bool rRmdir(const std::string& dir); -bool rMkdir(const std::string& dir); -bool rMkpath(const std::string& path); -bool rRename(const std::string &from, const std::string &to); -bool rExists(const std::string &path); -bool rDirExists(const std::string &path); -bool rFileExists(const std::string &path); -bool rRemoveFile(const std::string &path); - -bool rIsWritable(const std::string& path); -bool rIsReadable(const std::string& path); -bool rIsExecutable(const std::string& path); - struct rDir { rDir(); diff --git a/rpcs3/Crypto/unpkg.cpp b/rpcs3/Crypto/unpkg.cpp index 3d26e9178d..c08a3b5eab 100644 --- a/rpcs3/Crypto/unpkg.cpp +++ b/rpcs3/Crypto/unpkg.cpp @@ -191,7 +191,8 @@ int Unpack(rFile& pkg_f, std::string src, std::string dst) PKGHeader* m_header = (PKGHeader*) malloc (sizeof(PKGHeader)); rFile dec_pkg_f; - std::string decryptedFile = rGetCwd() + "/dev_hdd1/" + src + ".dec"; + // TODO: This shouldn't use current dir + std::string decryptedFile = "./dev_hdd1/" + src + ".dec"; dec_pkg_f.Create(decryptedFile, true); diff --git a/rpcs3/Crypto/unself.cpp b/rpcs3/Crypto/unself.cpp index eef46d2e28..d03091dae1 100644 --- a/rpcs3/Crypto/unself.cpp +++ b/rpcs3/Crypto/unself.cpp @@ -505,10 +505,11 @@ bool SELFDecrypter::GetKeyFromRap(u8 *content_id, u8 *npdrm_key) // Try to find a matching RAP file under dev_usb000. std::string ci_str((const char *)content_id); - std::string rap_path(rGetCwd() + "/dev_usb000/" + ci_str + ".rap"); + // TODO: This shouldn't use current dir + std::string rap_path("./dev_usb000/" + ci_str + ".rap"); // Check if we have a valid RAP file. - if (!rFile::Exists(rap_path)) + if (!rExists(rap_path)) { LOG_ERROR(LOADER, "This application requires a valid RAP file for decryption!"); return false; diff --git a/rpcs3/Emu/FS/VFS.cpp b/rpcs3/Emu/FS/VFS.cpp index 3c79002e13..1776343ce8 100644 --- a/rpcs3/Emu/FS/VFS.cpp +++ b/rpcs3/Emu/FS/VFS.cpp @@ -291,7 +291,8 @@ void VFS::Init(const std::string& path) } std::string mpath = entry.path; - fmt::Replace(mpath,"$(EmulatorDir)", rGetCwd()); + // TODO: This shouldn't use current dir + fmt::Replace(mpath,"$(EmulatorDir)", "."); fmt::Replace(mpath,"$(GameDir)", vfsDevice::GetRoot(path)); Mount(entry.mount, mpath, dev); } diff --git a/rpcs3/Emu/FS/vfsDirBase.cpp b/rpcs3/Emu/FS/vfsDirBase.cpp index 63e5908dd0..14f4fdfc45 100644 --- a/rpcs3/Emu/FS/vfsDirBase.cpp +++ b/rpcs3/Emu/FS/vfsDirBase.cpp @@ -32,7 +32,7 @@ bool vfsDirBase::IsOpened() const bool vfsDirBase::IsExists(const std::string& path) const { - return rDirExists(path); + return rExists(path); } const std::vector& vfsDirBase::GetEntries() const diff --git a/rpcs3/Emu/FS/vfsLocalDir.cpp b/rpcs3/Emu/FS/vfsLocalDir.cpp index e97f9a5ad7..69008fa03b 100644 --- a/rpcs3/Emu/FS/vfsLocalDir.cpp +++ b/rpcs3/Emu/FS/vfsLocalDir.cpp @@ -26,13 +26,18 @@ bool vfsLocalDir::Open(const std::string& path) std::string dir_path = path + name; m_entries.emplace_back(); + // TODO: Use same info structure as fileinfo? DirEntryInfo& info = m_entries.back(); info.name = name; - info.flags |= dir.Exists(dir_path) ? DirEntry_TypeDir : DirEntry_TypeFile; - if(rIsWritable(dir_path)) info.flags |= DirEntry_PermWritable; - if(rIsReadable(dir_path)) info.flags |= DirEntry_PermReadable; - if(rIsExecutable(dir_path)) info.flags |= DirEntry_PermExecutable; + FileInfo fileinfo; + getFileInfo(dir_path.c_str(), &fileinfo); + + // Not sure of purpose for below. I hope these don't need to be correct + info.flags |= rIsDir(dir_path) ? DirEntry_TypeDir : DirEntry_TypeFile; + if(fileinfo.isWritable) info.flags |= DirEntry_PermWritable; + info.flags |= DirEntry_PermReadable; // Always? + info.flags |= DirEntry_PermExecutable; // Always? } return true; diff --git a/rpcs3/Emu/FS/vfsLocalFile.cpp b/rpcs3/Emu/FS/vfsLocalFile.cpp index 7a6e71c09c..aea1e02e0c 100644 --- a/rpcs3/Emu/FS/vfsLocalFile.cpp +++ b/rpcs3/Emu/FS/vfsLocalFile.cpp @@ -63,7 +63,7 @@ bool vfsLocalFile::Create(const std::string& path) break; const std::string& dir = path.substr(0, p); - if(!rDirExists(dir)) + if(!rExists(dir)) { LOG_NOTICE(HLE, "create dir: %s", dir.c_str()); rMkdir(dir); @@ -72,7 +72,7 @@ bool vfsLocalFile::Create(const std::string& path) //create file const char m = path[path.length() - 1]; - if(m != '/' && m != '\\' && !rFileExists(path)) // ??? + if(m != '/' && m != '\\' && !rExists(path)) // ??? { rFile f; return f.Create(path); @@ -118,5 +118,5 @@ bool vfsLocalFile::IsOpened() const bool vfsLocalFile::Exists(const std::string& path) { - return rFileExists(path); + return rExists(path); } \ No newline at end of file diff --git a/rpcs3/Emu/GS/GL/GLGSRender.cpp b/rpcs3/Emu/GS/GL/GLGSRender.cpp index 184510d77b..24e7fb790c 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.cpp +++ b/rpcs3/Emu/GS/GL/GLGSRender.cpp @@ -359,7 +359,8 @@ bool GLGSRender::LoadProgram() m_shader_prog.Compile(); checkForGlError("m_shader_prog.Compile"); - rFile f(rGetCwd() + "/FragmentProgram.txt", rFile::write); + // TODO: This shouldn't use current dir + rFile f("./FragmentProgram.txt", rFile::write); f.Write(m_shader_prog.GetShaderText()); } @@ -372,7 +373,8 @@ bool GLGSRender::LoadProgram() m_vertex_prog.Compile(); checkForGlError("m_vertex_prog.Compile"); - rFile f(rGetCwd() + "/VertexProgram.txt", rFile::write); + // TODO: This shouldn't use current dir + rFile f("./VertexProgram.txt", rFile::write); f.Write(m_vertex_prog.shader); } diff --git a/rpcs3/Emu/GS/GL/GLGSRender.h b/rpcs3/Emu/GS/GL/GLGSRender.h index 8596ed0116..325bca7fa4 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.h +++ b/rpcs3/Emu/GS/GL/GLGSRender.h @@ -593,10 +593,10 @@ public: static const std::string& dir_path = "textures"; static const std::string& file_fmt = dir_path + "/" + "tex[%d].png"; - if(!rDirExists(dir_path)) rMkdir(dir_path); + if(!rExists(dir_path)) rMkdir(dir_path); u32 count = 0; - while(rFileExists(fmt::Format(file_fmt, count))) count++; + while(rExists(fmt::Format(file_fmt, count))) count++; Save(tex, fmt::Format(file_fmt, count)); } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp index aae129c92a..703c6eb3c8 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp @@ -660,7 +660,7 @@ int cellSysCacheClear(void) Emu.GetVFS().GetDevice(std::string("/dev_hdd1/cache/"), localPath); //TODO: implement - //if (rDirExists(localPath)){ + //if (rIsDir(localPath)){ // WxDirDeleteTraverser deleter; // wxString f = wxFindFirstFile(fmt::FromUTF8(localPath+"\\*"),wxDIR); // while (!f.empty()) diff --git a/rpcs3/Emu/SysCalls/Modules/sceNp.cpp b/rpcs3/Emu/SysCalls/Modules/sceNp.cpp index 6b5bce2a51..783adaaf48 100644 --- a/rpcs3/Emu/SysCalls/Modules/sceNp.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sceNp.cpp @@ -53,10 +53,12 @@ int sceNpDrmIsAvailable(u32 k_licensee_addr, u32 drm_path_addr) //make more explicit what this actually does (currently everything after the third slash and before the fourth slash) std::string titleID = fmt::BeforeFirst(fmt::AfterFirst(fmt::AfterFirst(fmt::AfterFirst(drm_path,'/'),'/'),'/'),'/'); - std::string enc_drm_path = rGetCwd() + drm_path; - std::string dec_drm_path = rGetCwd() + "/dev_hdd1/" + titleID + "/" + drm_file_name; + // TODO: These shouldn't use current dir + std::string enc_drm_path = drm_path; + drm_path.insert(0, 1, '.'); + std::string dec_drm_path = "./dev_hdd1/" + titleID + "/" + drm_file_name; - std::string rap_dir_path = rGetCwd() + "/dev_usb000/"; + std::string rap_dir_path = "./dev_usb000/"; std::string rap_file_path = rap_dir_path; // Search dev_usb000 for a compatible RAP file. @@ -77,9 +79,10 @@ int sceNpDrmIsAvailable(u32 k_licensee_addr, u32 drm_path_addr) } // Create a new directory under dev_hdd1/titleID to hold the decrypted data. - std::string tmp_dir = rGetCwd() + "/dev_hdd1/" + titleID; - if (!rDir::Exists(tmp_dir)) - rMkdir(rGetCwd() + "/dev_hdd1/" + titleID); + // TODO: These shouldn't use current dir + std::string tmp_dir = "./dev_hdd1/" + titleID; + if (!rExists(tmp_dir)) + rMkdir("./dev_hdd1/" + titleID); // Decrypt this EDAT using the supplied k_licensee and matching RAP file. DecryptEDAT(enc_drm_path, dec_drm_path, 8, rap_file_path, k_licensee, false); diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 0e66104969..554450d425 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -133,7 +133,7 @@ void Emulator::Load() { GetModuleManager().init(); - if(!rFileExists(m_path)) return; + if(!rExists(m_path)) return; if(IsSelf(m_path)) { diff --git a/rpcs3/Gui/GameViewer.cpp b/rpcs3/Gui/GameViewer.cpp index 467389aeeb..f709031bb8 100644 --- a/rpcs3/Gui/GameViewer.cpp +++ b/rpcs3/Gui/GameViewer.cpp @@ -241,7 +241,7 @@ void GameViewer::RemoveGame(wxCommandEvent& event) Emu.GetVFS().UnMountAll(); - if (!rFile::Exists(localPath)) + if (!rExists(localPath)) return; //TODO: Replace wxWidgetsSpecific filesystem stuff? WxDirDeleteTraverser deleter; diff --git a/rpcs3/Loader/PKG.cpp b/rpcs3/Loader/PKG.cpp index 7c055c35be..c07e43a5fa 100644 --- a/rpcs3/Loader/PKG.cpp +++ b/rpcs3/Loader/PKG.cpp @@ -13,7 +13,8 @@ bool PKGLoader::Install(std::string dest) if (!pkg_f.IsOpened()) return false; - dest = rGetCwd() + dest; + // TODO: This shouldn't use current dir + dest.insert(0, 1, '.'); if (!dest.empty() && dest.back() != '/') dest += '/'; @@ -24,7 +25,7 @@ bool PKGLoader::Install(std::string dest) std::string titleID = std::string(title_id).substr(7, 9); - if (rDirExists(dest+titleID)) { + if (rExists(dest+titleID)) { rMessageDialog d_overwrite(NULL, "Another installation was found. Do you want to overwrite it?", "PKG Decrypter / Installer", rYES_NO|rCENTRE); if (d_overwrite.ShowModal() != rID_YES) { LOG_ERROR(LOADER, "PKG Loader: Another installation found in: %s", titleID.c_str()); @@ -55,4 +56,4 @@ bool PKGLoader::Install(std::string dest) bool PKGLoader::Close() { return pkg_f.Close(); -} \ No newline at end of file +}