diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.cpp b/rpcs3/Emu/Cell/lv2/sys_fs.cpp index 2a4a03b55f..2fbfc6ff06 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_fs.cpp @@ -204,7 +204,7 @@ error_code sys_fs_open(vm::cptr path, s32 flags, vm::ptr fd, s32 mode // TODO: other checks for path - if (fs::is_dir(local_path)) + if (local_path == "/" || fs::is_dir(local_path)) { return {CELL_EISDIR, path}; } @@ -432,6 +432,11 @@ error_code sys_fs_opendir(vm::cptr path, vm::ptr fd) // TODO: other checks for path + if (local_path == "/") + { + return {CELL_EPERM, path}; + } + if (fs::is_file(local_path)) { return {CELL_ENOTDIR, path}; @@ -508,14 +513,20 @@ error_code sys_fs_stat(vm::cptr path, vm::ptr sb) { sys_fs.warning("sys_fs_stat(path=%s, sb=*0x%x)", path, sb); - const std::string& local_path = vfs::get(path.get_ptr()); + const std::string local_path = vfs::get(path.get_ptr()); if (local_path.empty()) { return {CELL_ENOTMOUNTED, path}; } - fs::stat_t info; + fs::stat_t info{}; + + if (local_path == "/") + { + sb->mode = CELL_FS_S_IFDIR | 0444; + return CELL_OK; + } if (!fs::stat(local_path, info)) { @@ -578,7 +589,19 @@ error_code sys_fs_mkdir(vm::cptr path, s32 mode) { sys_fs.warning("sys_fs_mkdir(path=%s, mode=%#o)", path, mode); - if (!fs::create_path(vfs::get(path.get_ptr()))) + const std::string local_path = vfs::get(path.get_ptr()); + + if (local_path.empty()) + { + return {CELL_ENOTMOUNTED, path}; + } + + if (local_path == "/") + { + return {CELL_EEXIST, path}; + } + + if (!fs::create_path(local_path)) { switch (auto error = fs::g_tls_error) { @@ -598,7 +621,20 @@ error_code sys_fs_rename(vm::cptr from, vm::cptr to) { sys_fs.warning("sys_fs_rename(from=%s, to=%s)", from, to); - if (!fs::rename(vfs::get(from.get_ptr()), vfs::get(to.get_ptr()), false)) + const std::string local_from = vfs::get(from.get_ptr()); + const std::string local_to = vfs::get(to.get_ptr()); + + if (local_from.empty() || local_to.empty()) + { + return CELL_ENOTMOUNTED; + } + + if (local_to == "/" || local_from == "/") + { + return CELL_EPERM; + } + + if (!fs::rename(local_from, local_to, false)) { switch (auto error = fs::g_tls_error) { @@ -618,7 +654,19 @@ error_code sys_fs_rmdir(vm::cptr path) { sys_fs.warning("sys_fs_rmdir(path=%s)", path); - if (!fs::remove_dir(vfs::get(path.get_ptr()))) + const std::string local_path = vfs::get(path.get_ptr()); + + if (local_path.empty()) + { + return {CELL_ENOTMOUNTED, path}; + } + + if (local_path == "/") + { + return {CELL_EPERM, path}; + } + + if (!fs::remove_dir(local_path)) { switch (auto error = fs::g_tls_error) { @@ -638,7 +686,19 @@ error_code sys_fs_unlink(vm::cptr path) { sys_fs.warning("sys_fs_unlink(path=%s)", path); - if (!fs::remove_file(vfs::get(path.get_ptr()))) + const std::string local_path = vfs::get(path.get_ptr()); + + if (local_path.empty()) + { + return {CELL_ENOTMOUNTED, path}; + } + + if (local_path == "/") + { + return {CELL_EISDIR, path}; + } + + if (!fs::remove_file(local_path)) { switch (auto error = fs::g_tls_error) { @@ -768,8 +828,20 @@ error_code sys_fs_fcntl(u32 fd, u32 op, vm::ptr _arg, u32 _size) { const auto arg = vm::static_ptr_cast(_arg); + const std::string local_path = vfs::get(arg->path.get_ptr()); + + if (local_path.empty()) + { + return {CELL_ENOTMOUNTED, arg->path}; + } + + if (local_path == "/") + { + return {CELL_EPERM, arg->path}; + } + fs::device_stat info; - if (!fs::statfs(vfs::get(arg->path.get_ptr()), info)) + if (!fs::statfs(local_path, info)) { switch (auto error = fs::g_tls_error) { @@ -1127,7 +1199,19 @@ error_code sys_fs_truncate(vm::cptr path, u64 size) { sys_fs.warning("sys_fs_truncate(path=%s, size=0x%llx)", path, size); - if (!fs::truncate_file(vfs::get(path.get_ptr()), size)) + const std::string local_path = vfs::get(path.get_ptr()); + + if (local_path.empty()) + { + return {CELL_ENOTMOUNTED, path}; + } + + if (local_path == "/") + { + return {CELL_EISDIR, path}; + } + + if (!fs::truncate_file(local_path, size)) { switch (auto error = fs::g_tls_error) { @@ -1207,8 +1291,20 @@ error_code sys_fs_disk_free(vm::ps3::cptr path, vm::ptr total_free, v { sys_fs.warning("sys_fs_disk_free(path=%s total_free=*0x%x avail_free=*0x%x)", path, total_free, avail_free); + const std::string local_path = vfs::get(path.get_ptr()); + + if (local_path.empty()) + { + return {CELL_ENOTMOUNTED, path}; + } + + if (local_path == "/") + { + return {CELL_EPERM, path}; + } + fs::device_stat info; - if (!fs::statfs(vfs::get(path.get_ptr()), info)) + if (!fs::statfs(local_path, info)) { switch (auto error = fs::g_tls_error) { @@ -1229,7 +1325,19 @@ error_code sys_fs_utime(vm::ps3::cptr path, vm::ps3::cptr t { sys_fs.warning("sys_fs_utime(path=%s, timep=*0x%x)", path, timep); - if (!fs::utime(vfs::get(path.get_ptr()), timep->actime, timep->modtime)) + const std::string local_path = vfs::get(path.get_ptr()); + + if (local_path.empty()) + { + return {CELL_ENOTMOUNTED, path}; + } + + if (local_path == "/") + { + return {CELL_EISDIR, path}; + } + + if (!fs::utime(local_path, timep->actime, timep->modtime)) { switch (auto error = fs::g_tls_error) { diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index ea0f7beaeb..3d0c28abaf 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -360,6 +360,7 @@ void Emulator::Load(bool add_only) vfs::mount("dev_usb", fmt::replace_all(g_cfg.vfs.dev_usb000, "$(EmulatorDir)", emu_dir)); vfs::mount("dev_usb000", fmt::replace_all(g_cfg.vfs.dev_usb000, "$(EmulatorDir)", emu_dir)); vfs::mount("app_home", home_dir.empty() ? elf_dir + '/' : fmt::replace_all(home_dir, "$(EmulatorDir)", emu_dir)); + vfs::mount("", elf_dir + '/'); // Detect boot location const std::string hdd0_game = vfs::get("/dev_hdd0/game/"); diff --git a/rpcs3/Emu/VFS.cpp b/rpcs3/Emu/VFS.cpp index 4ec9670e70..b56a749847 100644 --- a/rpcs3/Emu/VFS.cpp +++ b/rpcs3/Emu/VFS.cpp @@ -26,24 +26,36 @@ bool vfs::mount(const std::string& dev_name, const std::string& path) std::string vfs::get(const std::string& vpath, vfs::type _type) { + const auto table = fxm::get_always(); + + reader_lock lock(table->mutex); + std::smatch match; if (!std::regex_match(vpath, match, _type == type::ps3 ? s_regex_ps3 : s_regex_psv)) { - LOG_WARNING(GENERAL, "vfs::get(): invalid input: %s", vpath); - return{}; + const auto found = table->mounted.find(""); + + if (found == table->mounted.end()) + { + LOG_WARNING(GENERAL, "vfs::get(): no default directory: %s", vpath); + return {}; + } + + return found->second + vpath; } - const auto table = fxm::get_always(); - - reader_lock lock(table->mutex); + if (_type == type::ps3 && match.length(1) == 0) + { + return "/"; + } const auto found = table->mounted.find(match.str(1)); if (found == table->mounted.end()) { LOG_WARNING(GENERAL, "vfs::get(): device not found: %s", vpath); - return{}; + return {}; } // Concatenate