diff --git a/Utilities/AutoPause.cpp b/Utilities/AutoPause.cpp index f92ccd1cc0..0193fb8e3c 100644 --- a/Utilities/AutoPause.cpp +++ b/Utilities/AutoPause.cpp @@ -44,7 +44,7 @@ AutoPause::~AutoPause(void) //This would be able to create in a GUI window. void AutoPause::Reload(void) { - if (rExists("pause.bin")) + if (rIsFile("pause.bin")) { m_pause_function.clear(); m_pause_function.reserve(16); diff --git a/Utilities/rFile.cpp b/Utilities/rFile.cpp index 5ad8a67a3c..1dbce8b4af 100644 --- a/Utilities/rFile.cpp +++ b/Utilities/rFile.cpp @@ -126,6 +126,37 @@ bool get_file_info(const std::string& path, FileInfo& info) return true; } +bool rExists(const std::string& path) +{ +#ifdef _WIN32 + return GetFileAttributesW(ConvertUTF8ToWChar(path).get()) != 0xFFFFFFFF; +#else + struct stat buffer; + return stat(path.c_str(), &buffer) == 0; +#endif +} + +bool rIsFile(const std::string& file) +{ +#ifdef _WIN32 + DWORD attrs; + if ((attrs = GetFileAttributesW(ConvertUTF8ToWChar(file).get())) == INVALID_FILE_ATTRIBUTES) + { + return false; + } + + return (attrs & FILE_ATTRIBUTE_DIRECTORY) == 0; +#else + struct stat64 file_info; + if (stat64(file.c_str(), &file_info) < 0) + { + return false; + } + + return !S_ISDIR(file_info.st_mode); +#endif +} + bool rIsDir(const std::string& dir) { #ifdef _WIN32 @@ -147,7 +178,7 @@ bool rIsDir(const std::string& dir) #endif } -bool rMkdir(const std::string& dir) +bool rMkDir(const std::string& dir) { #ifdef _WIN32 if (!CreateDirectoryW(ConvertUTF8ToWChar(dir).get(), NULL)) @@ -162,34 +193,49 @@ bool rMkdir(const std::string& dir) return true; } -bool rMkpath(const std::string& path) +bool rMkPath(const std::string& path) { - size_t start=0, pos; - std::string dir; - bool ret; + size_t start = 0; - while (true) { - if ((pos = path.find_first_of("/\\", start)) == std::string::npos) + while (true) + { + // maybe it could be more optimal if goes from the end recursively + size_t pos = path.find_first_of("/\\", start); + + if (pos == std::string::npos) + { pos = path.length(); - - dir = path.substr(0,pos++); - start = pos; - if(dir.size() == 0) - continue; -#ifdef _WIN32 - if((ret = _mkdir(dir.c_str()) != 0) && errno != EEXIST){ -#else - if((ret = mkdir(dir.c_str(), 0777) != 0) && errno != EEXIST){ -#endif - return !ret; } + + std::string dir = path.substr(0, pos); + + start = ++pos; + + if (dir.size() == 0) + { + continue; + } + + if (!rIsDir(dir)) + { + // if doesn't exist or not a dir + if (!rMkDir(dir)) + { + // if creating failed + return false; + } + } + if (pos >= path.length()) - return true; + { + break; + } } + return true; } -bool rRmdir(const std::string& dir) +bool rRmDir(const std::string& dir) { #ifdef _WIN32 if (!RemoveDirectoryW(ConvertUTF8ToWChar(dir).get())) @@ -271,16 +317,6 @@ bool rCopy(const std::string& from, const std::string& to, bool overwrite) return true; } -bool rExists(const std::string& file) -{ -#ifdef _WIN32 - return GetFileAttributesW(ConvertUTF8ToWChar(file).get()) != 0xFFFFFFFF; -#else - struct stat buffer; - return stat(file.c_str(), &buffer) == 0; -#endif -} - bool rRemoveFile(const std::string& file) { #ifdef _WIN32 @@ -386,6 +422,7 @@ bool rfile_t::open(const std::string& filename, u32 mode) case o_trunc: disp = TRUNCATE_EXISTING; break; case o_create | o_trunc: disp = CREATE_ALWAYS; break; case o_create | o_excl: disp = CREATE_NEW; break; + case o_create | o_excl | o_trunc: disp = CREATE_NEW; break; } if (!disp || (mode & ~(o_read | o_write | o_create | o_trunc | o_excl))) @@ -414,7 +451,7 @@ bool rfile_t::open(const std::string& filename, u32 mode) if (mode & o_trunc) flags |= O_TRUNC; if (mode & o_excl) flags |= O_EXCL; - if (((mode & o_excl) && (!(mode & o_create) || (mode & o_trunc))) || (mode & ~(o_read | o_write | o_create | o_trunc | o_excl))) + if (((mode & o_excl) && !(mode & o_create)) || (mode & ~(o_read | o_write | o_create | o_trunc | o_excl))) { LOG_ERROR(GENERAL, "rfile_t::open('%s') failed: unknown mode specified (0x%x)", filename, mode); return false; diff --git a/Utilities/rFile.h b/Utilities/rFile.h index 208f320ec8..93bb522053 100644 --- a/Utilities/rFile.h +++ b/Utilities/rFile.h @@ -12,13 +12,14 @@ struct FileInfo }; bool get_file_info(const std::string& path, FileInfo& fileInfo); +bool rExists(const std::string& path); +bool rIsFile(const std::string& file); bool rIsDir(const std::string& dir); -bool rRmdir(const std::string& dir); -bool rMkdir(const std::string& dir); -bool rMkpath(const std::string& path); +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 rCopy(const std::string& from, const std::string& to, bool overwrite); -bool rExists(const std::string& file); bool rRemoveFile(const std::string& file); bool rTruncate(const std::string& file, uint64_t length); diff --git a/rpcs3/Crypto/unpkg.cpp b/rpcs3/Crypto/unpkg.cpp index e96895055c..9386c13581 100644 --- a/rpcs3/Crypto/unpkg.cpp +++ b/rpcs3/Crypto/unpkg.cpp @@ -186,7 +186,7 @@ bool UnpackEntry(const rfile_t& dec_pkg_f, const PKGEntry& entry, std::string di { auto path = dir + std::string(buf, entry.name_size); - if (rExists(path)) + if (rIsFile(path)) { LOG_WARNING(LOADER, "PKG Loader: '%s' is overwritten", path); } @@ -218,7 +218,7 @@ bool UnpackEntry(const rfile_t& dec_pkg_f, const PKGEntry& entry, std::string di case PKG_FILE_ENTRY_FOLDER: { auto path = dir + std::string(buf, entry.name_size); - if (!rExists(path) && !rMkdir(path)) + if (!rIsDir(path) && !rMkPath(path)) { LOG_ERROR(LOADER, "PKG Loader: Could not create directory: %s", path.c_str()); return false; diff --git a/rpcs3/Crypto/unself.cpp b/rpcs3/Crypto/unself.cpp index 59a755d30b..1ad55c49bc 100644 --- a/rpcs3/Crypto/unself.cpp +++ b/rpcs3/Crypto/unself.cpp @@ -1192,7 +1192,7 @@ bool SELFDecrypter::GetKeyFromRap(u8 *content_id, u8 *npdrm_key) std::string rap_path("dev_hdd0/home/" + pf_str + "/exdata/" + ci_str + ".rap"); // Check if we have a valid RAP file. - if (!rExists(rap_path)) + if (!rIsFile(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 f43c0b4c51..f8046a8344 100644 --- a/rpcs3/Emu/FS/VFS.cpp +++ b/rpcs3/Emu/FS/VFS.cpp @@ -181,6 +181,18 @@ bool VFS::CreateDir(const std::string& ps3_path) const return false; } +bool VFS::CreatePath(const std::string& ps3_path) const +{ + std::string path; + + if (vfsDevice* dev = GetDevice(ps3_path, path)) + { + return rMkPath(path); + } + + return false; +} + bool VFS::RemoveFile(const std::string& ps3_path) const { std::string path; diff --git a/rpcs3/Emu/FS/VFS.h b/rpcs3/Emu/FS/VFS.h index dfe14048b9..b01cfe102a 100644 --- a/rpcs3/Emu/FS/VFS.h +++ b/rpcs3/Emu/FS/VFS.h @@ -81,6 +81,7 @@ struct VFS vfsFileBase* OpenFile(const std::string& ps3_path, u32 mode) const; vfsDirBase* OpenDir(const std::string& ps3_path) const; bool CreateDir(const std::string& ps3_path) const; + bool CreatePath(const std::string& ps3_path) const; bool RemoveFile(const std::string& ps3_path) const; bool RemoveDir(const std::string& ps3_path) const; bool ExistsFile(const std::string& ps3_path) const; diff --git a/rpcs3/Emu/FS/vfsLocalDir.cpp b/rpcs3/Emu/FS/vfsLocalDir.cpp index 3d88c57b28..f9d456f868 100644 --- a/rpcs3/Emu/FS/vfsLocalDir.cpp +++ b/rpcs3/Emu/FS/vfsLocalDir.cpp @@ -42,7 +42,7 @@ bool vfsLocalDir::Open(const std::string& path) bool vfsLocalDir::Create(const std::string& path) { - return rMkdir(path); + return rMkDir(path); } bool vfsLocalDir::IsExists(const std::string& path) const @@ -57,7 +57,7 @@ bool vfsLocalDir::Rename(const std::string& from, const std::string& to) bool vfsLocalDir::Remove(const std::string& path) { - return rRmdir(path); + return rRmDir(path); } bool vfsLocalDir::IsOpened() const diff --git a/rpcs3/Emu/FS/vfsLocalFile.cpp b/rpcs3/Emu/FS/vfsLocalFile.cpp index 5bb7408b06..8d1ea4c405 100644 --- a/rpcs3/Emu/FS/vfsLocalFile.cpp +++ b/rpcs3/Emu/FS/vfsLocalFile.cpp @@ -50,7 +50,7 @@ bool vfsLocalFile::IsOpened() const bool vfsLocalFile::Exists(const std::string& path) { - return rExists(path); + return rIsFile(path); } bool vfsLocalFile::Rename(const std::string& from, const std::string& to) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index f794e88044..9a72e08aeb 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -610,10 +610,10 @@ void GLTexture::Save(RSXTexture& tex) static const std::string& dir_path = "textures"; static const std::string& file_fmt = dir_path + "/" + "tex[%d].png"; - if (!rExists(dir_path)) rMkdir(dir_path); + if (!rIsDir(dir_path)) rMkDir(dir_path); u32 count = 0; - while (rExists(fmt::Format(file_fmt.c_str(), count))) count++; + while (rIsFile(fmt::Format(file_fmt.c_str(), count))) count++; Save(tex, fmt::Format(file_fmt.c_str(), count)); } diff --git a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp index cccc65d902..bf67d13c96 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp @@ -13,8 +13,8 @@ extern Module cellGame; -std::string contentInfo = ""; -std::string usrdir = ""; +std::string contentInfo; +std::string usrdir; bool path_set = false; s32 cellHddGameCheck(PPUThread& CPU, u32 version, vm::ptr dirName, u32 errDialog, vm::ptr funcStat, u32 container) @@ -250,7 +250,7 @@ s32 cellGameContentPermit(vm::ptr contentInfoPath, vm: { cellGame.Warning("cellGameContentPermit(contentInfoPath=*0x%x, usrdirPath=*0x%x)", contentInfoPath, usrdirPath); - if (!contentInfoPath || !usrdirPath) + if (!contentInfoPath && !usrdirPath) { return CELL_GAME_ERROR_PARAM; } @@ -262,6 +262,17 @@ s32 cellGameContentPermit(vm::ptr contentInfoPath, vm: return CELL_GAME_ERROR_FAILURE; } + if (contentInfo.size() == 9 && usrdir.empty()) + { + if (Emu.GetVFS().RenameDir("/dev_hdd0/game/TMP_" + contentInfo, "/dev_hdd0/game/" + contentInfo)) + { + cellGame.Success("cellGameContentPermit(): gamedata directory created ('/dev_hdd0/game/%s')", contentInfo); + } + + contentInfo = "/dev_hdd0/game/" + contentInfo; + usrdir = contentInfo + "/USRDIR"; + } + strcpy_trunc(*contentInfoPath, contentInfo); strcpy_trunc(*usrdirPath, usrdir); @@ -381,28 +392,31 @@ s32 cellGameCreateGameData(vm::ptr init, vm::ptrtitle; - contentInfo = "/dev_hdd0/game/" + title; - usrdir = "/dev_hdd0/game/" + title + "/USRDIR"; + std::string dir = init->titleId; + std::string tmp_contentInfo = "/dev_hdd0/game/TMP_" + dir; + std::string tmp_usrdir = "/dev_hdd0/game/TMP_" + dir + "/USRDIR"; - if (!Emu.GetVFS().CreateDir(contentInfo)) + if (!Emu.GetVFS().CreateDir(tmp_contentInfo)) { - cellGame.Error("cellGameCreateGameData(): failed to create content directory ('%s')", contentInfo); + cellGame.Error("cellGameCreateGameData(): failed to create content directory ('%s')", tmp_contentInfo); return CELL_GAME_ERROR_ACCESS_ERROR; // ??? } - if (!Emu.GetVFS().CreateDir(usrdir)) + if (!Emu.GetVFS().CreateDir(tmp_usrdir)) { - cellGame.Error("cellGameCreateGameData(): failed to create USRDIR directory ('%s')", usrdir); + cellGame.Error("cellGameCreateGameData(): failed to create USRDIR directory ('%s')", tmp_usrdir); return CELL_GAME_ERROR_ACCESS_ERROR; // ??? } // cellGameContentPermit should then move files in non-temporary location and return their non-temporary displacement - strcpy_trunc(*tmp_contentInfoPath, contentInfo); - strcpy_trunc(*tmp_usrdirPath, usrdir); + strcpy_trunc(*tmp_contentInfoPath, tmp_contentInfo); + strcpy_trunc(*tmp_usrdirPath, tmp_usrdir); + + contentInfo = dir; + usrdir.clear(); path_set = true; - cellGame.Success("cellGameCreateGameData(): gamedata directory created ('%s')", contentInfo); + cellGame.Success("cellGameCreateGameData(): temporary gamedata directory created ('%s')", tmp_contentInfo); // TODO: set initial PARAM.SFO parameters diff --git a/rpcs3/Emu/SysCalls/lv2/sys_fs.cpp b/rpcs3/Emu/SysCalls/lv2/sys_fs.cpp index dd40006839..1ff4bf615c 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_fs.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_fs.cpp @@ -62,7 +62,7 @@ s32 sys_fs_open(vm::ptr path, s32 flags, vm::ptr fd, s32 mode, if (flags & CELL_FS_O_EXCL) { - if ((flags & CELL_FS_O_CREAT) && !(flags & CELL_FS_O_TRUNC)) + if (flags & CELL_FS_O_CREAT) { open_mode |= o_excl; } @@ -93,6 +93,12 @@ s32 sys_fs_open(vm::ptr path, s32 flags, vm::ptr fd, s32 mode, if (!file || !file->IsOpened()) { sys_fs.Error("sys_fs_open(): failed to open '%s' (flags=%#o, mode=%#o)", path.get_ptr(), flags, mode); + + if (open_mode & o_excl) + { + return CELL_FS_EEXIST; // approximation + } + return CELL_FS_ENOENT; } @@ -334,7 +340,7 @@ s32 sys_fs_mkdir(vm::ptr path, s32 mode) return CELL_FS_EEXIST; } - if (!Emu.GetVFS().CreateDir(_path)) + if (!Emu.GetVFS().CreatePath(_path)) { return CELL_FS_EIO; // ??? } @@ -384,14 +390,14 @@ s32 sys_fs_rmdir(vm::ptr path) std::string _path = path.get_ptr(); + if (!Emu.GetVFS().ExistsDir(_path)) + { + return CELL_FS_ENOENT; + } + if (!Emu.GetVFS().RemoveDir(_path)) { - if (Emu.GetVFS().ExistsDir(_path)) - { - return CELL_FS_EIO; // ??? - } - - return CELL_FS_ENOENT; + return CELL_FS_EIO; // ??? } sys_fs.Notice("sys_fs_rmdir(): directory '%s' removed", path.get_ptr()); @@ -405,14 +411,14 @@ s32 sys_fs_unlink(vm::ptr path) std::string _path = path.get_ptr(); + if (!Emu.GetVFS().ExistsFile(_path)) + { + return CELL_FS_ENOENT; + } + if (!Emu.GetVFS().RemoveFile(_path)) { - if (Emu.GetVFS().ExistsFile(_path)) - { - return CELL_FS_EIO; // ??? - } - - return CELL_FS_ENOENT; + return CELL_FS_EIO; // ??? } sys_fs.Notice("sys_fs_unlink(): file '%s' deleted", path.get_ptr()); diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index f5ee8d4b15..f6dbac5d38 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -182,7 +182,7 @@ void Emulator::Load() { GetModuleManager().Init(); - if (!rExists(m_path)) return; + if (!rIsFile(m_path)) return; if (IsSelf(m_path)) { @@ -407,7 +407,7 @@ void Emulator::SavePoints(const std::string& path) void Emulator::LoadPoints(const std::string& path) { - if (!rExists(path)) return; + if (!rIsFile(path)) return; std::ifstream f(path, std::ios::binary); if (!f.is_open()) return; diff --git a/rpcs3/Gui/AutoPauseManager.cpp b/rpcs3/Gui/AutoPauseManager.cpp index 4954452f61..66f86355b8 100644 --- a/rpcs3/Gui/AutoPauseManager.cpp +++ b/rpcs3/Gui/AutoPauseManager.cpp @@ -71,7 +71,7 @@ void AutoPauseManagerDialog::LoadEntries(void) m_entries.clear(); m_entries.reserve(16); - if (rExists("pause.bin")) + if (rIsFile("pause.bin")) { rfile_t list("pause.bin"); //System calls ID and Function calls ID are all u32 iirc. diff --git a/rpcs3/Loader/PKG.cpp b/rpcs3/Loader/PKG.cpp index 7a20598c83..a87f7af6c3 100644 --- a/rpcs3/Loader/PKG.cpp +++ b/rpcs3/Loader/PKG.cpp @@ -27,7 +27,7 @@ bool PKGLoader::Install(const rfile_t& pkg_f, std::string dest) std::string titleID = std::string(title_id).substr(7, 9); - if (rExists(dest + titleID)) + if (rIsDir(dest + titleID)) { if (rMessageDialog(NULL, "Another installation found. Do you want to overwrite it?", "PKG Decrypter / Installer", rYES_NO | rCENTRE).ShowModal() != rID_YES) { @@ -35,7 +35,7 @@ bool PKGLoader::Install(const rfile_t& pkg_f, std::string dest) return false; } } - else if (!rMkdir(dest + titleID)) + else if (!rMkDir(dest + titleID)) { LOG_ERROR(LOADER, "PKG Loader: Could not create the installation directory: %s", titleID.c_str()); return false; diff --git a/rpcs3/Loader/TROPUSR.cpp b/rpcs3/Loader/TROPUSR.cpp index 31f99d86f4..d7ba52d755 100644 --- a/rpcs3/Loader/TROPUSR.cpp +++ b/rpcs3/Loader/TROPUSR.cpp @@ -22,7 +22,6 @@ bool TROPUSRLoader::Load(const std::string& filepath, const std::string& configp if (m_file) Close(); - // TODO: This seems to be always true... A bug in ExistsFile() ? if (!Emu.GetVFS().ExistsFile(filepath)) Generate(filepath, configpath);