From 61a371b1068d5734ba5cad5c8be36de305762dcf Mon Sep 17 00:00:00 2001 From: brian218 Date: Fri, 28 Oct 2022 04:53:12 +0800 Subject: [PATCH] Implemented sys_fs_mount() and sys_fs_unmount() --- rpcs3/Emu/Cell/lv2/lv2.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_fs.cpp | 111 ++++++++++++++++++++++++++++++++-- rpcs3/Emu/Cell/lv2/sys_fs.h | 3 + rpcs3/Emu/System.cpp | 18 +++--- rpcs3/Emu/VFS.cpp | 8 ++- rpcs3/Emu/VFS.h | 2 +- 6 files changed, 126 insertions(+), 18 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/lv2.cpp b/rpcs3/Emu/Cell/lv2/lv2.cpp index ca776db0eb..62a26f3163 100644 --- a/rpcs3/Emu/Cell/lv2/lv2.cpp +++ b/rpcs3/Emu/Cell/lv2/lv2.cpp @@ -790,7 +790,7 @@ const std::array, 1024> g_ppu_sysc BIND_SYSC(sys_fs_chown), //835 (0x343) NULL_FUNC(sys_fs_newfs), //836 (0x344) BIND_SYSC(sys_fs_mount), //837 (0x345) - NULL_FUNC(sys_fs_unmount), //838 (0x346) + BIND_SYSC(sys_fs_unmount), //838 (0x346) NULL_FUNC(sys_fs_sync), //839 (0x347) BIND_SYSC(sys_fs_disk_free), //840 (0x348) BIND_SYSC(sys_fs_get_mount_info_size), //841 (0x349) diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.cpp b/rpcs3/Emu/Cell/lv2/sys_fs.cpp index 28deacba35..474527d019 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_fs.cpp @@ -10,6 +10,8 @@ #include "Emu/VFS.h" #include "Emu/vfs_config.h" #include "Emu/IdManager.h" +#include "Emu/system_utils.hpp" +#include "Emu/Cell/lv2/sys_process.h" #include "Emu/RSX/Overlays/overlay_utils.h" // for ascii8_to_utf16 #include "Utilities/StrUtil.h" @@ -119,7 +121,7 @@ bool verify_mself(const fs::file& mself_file) return true; } -lv2_fs_mount_point* lv2_fs_object::get_mp(std::string_view filename) +std::string_view lv2_fs_object::get_device_path(std::string_view filename) { std::string_view mp_name, vpath = filename; @@ -131,7 +133,7 @@ lv2_fs_mount_point* lv2_fs_object::get_mp(std::string_view filename) if (pos == 0) { // Relative path (TODO) - return &g_mp_sys_no_device; + return {}; } if (pos == umax) @@ -169,6 +171,13 @@ lv2_fs_mount_point* lv2_fs_object::get_mp(std::string_view filename) } } + return mp_name; +} + +lv2_fs_mount_point* lv2_fs_object::get_mp(std::string_view filename) +{ + const auto mp_name = get_device_path(filename); + if (!mp_name.empty()) { if (mp_name == "dev_hdd0"sv) @@ -200,6 +209,41 @@ lv2_fs_mount_point* lv2_fs_object::get_mp(std::string_view filename) return &g_mp_sys_dev_root; } +std::string lv2_fs_object::get_vfs(std::string_view filename) +{ + const auto mp_name = get_device_path(filename); + + if (!mp_name.empty()) + { + if (mp_name == "dev_hdd0"sv) + return g_cfg_vfs.get(g_cfg_vfs.dev_hdd0, rpcs3::utils::get_emu_dir()); + if (mp_name == "dev_hdd1"sv) + return g_cfg_vfs.get(g_cfg_vfs.dev_hdd1, rpcs3::utils::get_emu_dir()); + if (mp_name.starts_with("dev_usb"sv)) + return g_cfg_vfs.get_device(g_cfg_vfs.dev_usb, fmt::format("/%s", mp_name), rpcs3::utils::get_emu_dir()).path; + if (mp_name == "dev_bdvd"sv) + return g_cfg_vfs.get(g_cfg_vfs.dev_bdvd, rpcs3::utils::get_emu_dir()); + if (mp_name == "dev_ps2disc"sv) + return {}; // Unsupported in VFS + if (mp_name == "app_home"sv && filename.data() != Emu.argv[0].data()) + return lv2_fs_object::get_vfs(Emu.argv[0]); + if (mp_name == "host_root"sv) + return {}; // Unsupported in VFS + if (mp_name == "dev_flash"sv) + return g_cfg_vfs.get_dev_flash(); + if (mp_name == "dev_flash2"sv) + return g_cfg_vfs.get_dev_flash2(); + if (mp_name == "dev_flash3"sv) + return g_cfg_vfs.get_dev_flash3(); + + // Default + return g_cfg_vfs.get(g_cfg_vfs.dev_hdd0, rpcs3::utils::get_emu_dir()); + } + + // Default fallback + return {}; +} + lv2_fs_object::lv2_fs_object(utils::serial& ar, bool) : name(ar) , mp(get_mp(name.data())) @@ -2895,7 +2939,7 @@ error_code sys_fs_get_mount_info_size(ppu_thread&, vm::ptr len) return CELL_EFAULT; } - *len = 0x8; + *len = 0x9; return CELL_OK; } @@ -2915,7 +2959,7 @@ error_code sys_fs_get_mount_info(ppu_thread&, vm::ptr info, u32 sys_fs.todo("sys_fs_get_mount_info special case TODO"); } - const u32 max_len = std::min(len, 8); + const u32 max_len = std::min(len, 9); *out_len = max_len; struct mount_info @@ -2924,7 +2968,7 @@ error_code sys_fs_get_mount_info(ppu_thread&, vm::ptr info, u32 be_t unk1 = 0, unk2 = 0, unk3 = 0, unk4 = 0, unk5 = 0; }; - static constexpr std::array data + static constexpr std::array data { mount_info{.path = "/", .filesystem = "CELL_FS_ADMINFS", .dev_name = "CELL_FS_ADMINFS:", .unk5 = 0x10000000}, mount_info{.path = "/app_home", .filesystem = "CELL_FS_DUMMY", .dev_name = "CELL_FS_DUMMY:"}, @@ -2933,6 +2977,7 @@ error_code sys_fs_get_mount_info(ppu_thread&, vm::ptr info, u32 mount_info{.path = "/dev_flash2", .filesystem = "CELL_FS_FAT", .dev_name = "CELL_FS_IOS:BUILTIN_FLSH2:"}, mount_info{.path = "/dev_flash3", .filesystem = "CELL_FS_FAT", .dev_name = "CELL_FS_IOS:BUILTIN_FLSH3:"}, mount_info{.path = "/dev_hdd0", .filesystem = "CELL_FS_UFS", .dev_name = "CELL_FS_UTILITY:HDD0:"}, + mount_info{.path = "/dev_hdd1", .filesystem = "CELL_FS_FAT", .dev_name = "CELL_FS_UTILITY:HDD1:"}, mount_info{.path = "/dev_bdvd", .filesystem = "CELL_FS_ISO9660", .dev_name = "CELL_FS_IOS:PATA0_BDVD_DRIVE"}, }; @@ -2949,7 +2994,61 @@ error_code sys_fs_get_mount_info(ppu_thread&, vm::ptr info, u32 error_code sys_fs_mount(ppu_thread&, vm::cptr dev_name, vm::cptr file_system, vm::cptr path, s32 unk1, s32 prot, s32 unk3, vm::cptr str1, u32 str_len) { - sys_fs.todo("sys_fs_mount(dev_name=%s, file_system=%s, path=%s, unk1=0x%x, prot=0x%x, unk3=0x%x, str1=%s, str_len=%d)", dev_name, file_system, path, unk1, prot, unk3, str1, str_len); + sys_fs.warning("sys_fs_mount(dev_name=%s, file_system=%s, path=%s, unk1=0x%x, prot=0x%x, unk3=0x%x, str1=%s, str_len=%d)", dev_name, file_system, path, unk1, prot, unk3, str1, str_len); + + if (!g_ps3_process_info.has_root_perm()) + { + return CELL_ENOSYS; + } + + const auto [path_error, vpath] = translate_to_sv(path); + + if (path_error) + { + return { path_error, vpath }; + } + + const auto mp = lv2_fs_object::get_mp(vpath); + bool success = true; + + if (mp == &g_mp_sys_dev_hdd1) + { + const std::string_view appname = g_ps3_process_info.get_cellos_appname(); + success = vfs::mount(vpath, fmt::format("%s/caches/%s", lv2_fs_object::get_vfs(vpath), appname.substr(0, appname.find_last_of('.'))), true); + } + else + { + //success = vfs::mount(vpath, lv2_fs_object::get_vfs(vpath)); // We are not supporting mounting devices other than /dev_hdd1 via this syscall currently + } + + if (!success) + return CELL_EIO; + + return CELL_OK; +} + +error_code sys_fs_unmount(ppu_thread&, vm::cptr path, s32 unk1, s32 unk2) +{ + sys_fs.warning("sys_fs_unmount(path=%s, unk1=0x%x, unk2=0x%x)", path, unk1, unk2); + + if (!g_ps3_process_info.has_root_perm()) + { + return CELL_ENOSYS; + } + + const auto [path_error, vpath] = translate_to_sv(path); + + if (path_error) + { + return { path_error, vpath }; + } + + bool success = true; + + //success = vfs::unmount(vpath); // Not really unmounting it at the moment + + if (!success) + return CELL_EIO; return CELL_OK; } diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.h b/rpcs3/Emu/Cell/lv2/sys_fs.h index 615cac02b8..b9c21f7a40 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.h +++ b/rpcs3/Emu/Cell/lv2/sys_fs.h @@ -186,7 +186,9 @@ public: lv2_fs_object& operator=(const lv2_fs_object&) = delete; + static std::string_view get_device_path(std::string_view filename); static lv2_fs_mount_point* get_mp(std::string_view filename); + static std::string get_vfs(std::string_view filename); static std::array get_name(std::string_view filename) { @@ -615,5 +617,6 @@ error_code sys_fs_mapped_allocate(ppu_thread& ppu, u32 fd, u64, vm::pptr o error_code sys_fs_mapped_free(ppu_thread& ppu, u32 fd, vm::ptr ptr); error_code sys_fs_truncate2(ppu_thread& ppu, u32 fd, u64 size); error_code sys_fs_mount(ppu_thread& ppu, vm::cptr dev_name, vm::cptr file_system, vm::cptr path, s32 unk1, s32 prot, s32 unk3, vm::cptr str1, u32 str_len); +error_code sys_fs_unmount(ppu_thread&, vm::cptr path, s32 unk1, s32 unk2); error_code sys_fs_get_mount_info_size(ppu_thread& ppu, vm::ptr len); error_code sys_fs_get_mount_info(ppu_thread& ppu, vm::ptr info, u32 len, vm::ptr out_len); diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index f907439a09..4f0ce49761 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -245,14 +245,14 @@ void Emulator::Init(bool add_only) const std::string dev_bdvd = g_cfg_vfs.get(g_cfg_vfs.dev_bdvd, emu_dir); // Only used for make_path const std::string dev_hdd0 = g_cfg_vfs.get(g_cfg_vfs.dev_hdd0, emu_dir); const std::string dev_hdd1 = g_cfg_vfs.get(g_cfg_vfs.dev_hdd1, emu_dir); - const std::string dev_flsh = g_cfg_vfs.get_dev_flash(); - const std::string dev_flsh2 = g_cfg_vfs.get_dev_flash2(); - const std::string dev_flsh3 = g_cfg_vfs.get_dev_flash3(); + const std::string dev_flash = g_cfg_vfs.get_dev_flash(); + const std::string dev_flash2 = g_cfg_vfs.get_dev_flash2(); + const std::string dev_flash3 = g_cfg_vfs.get_dev_flash3(); vfs::mount("/dev_hdd0", dev_hdd0); - vfs::mount("/dev_flash", dev_flsh); - vfs::mount("/dev_flash2", dev_flsh2); - vfs::mount("/dev_flash3", dev_flsh3); + vfs::mount("/dev_flash", dev_flash); + vfs::mount("/dev_flash2", dev_flash2); + vfs::mount("/dev_flash3", dev_flash3); vfs::mount("/app_home", g_cfg_vfs.app_home.to_string().empty() ? elf_dir + '/' : g_cfg_vfs.get(g_cfg_vfs.app_home, emu_dir)); std::string dev_usb; @@ -351,9 +351,9 @@ void Emulator::Init(bool add_only) make_path_verbose(dev_bdvd); make_path_verbose(dev_hdd0); make_path_verbose(dev_hdd1); - make_path_verbose(dev_flsh); - make_path_verbose(dev_flsh2); - make_path_verbose(dev_flsh3); + make_path_verbose(dev_flash); + make_path_verbose(dev_flash2); + make_path_verbose(dev_flash3); make_path_verbose(dev_usb); make_path_verbose(dev_hdd0 + "game/"); make_path_verbose(dev_hdd0 + reinterpret_cast(u8"game/$locks/")); diff --git a/rpcs3/Emu/VFS.cpp b/rpcs3/Emu/VFS.cpp index 261d53fd91..f13e8f3703 100644 --- a/rpcs3/Emu/VFS.cpp +++ b/rpcs3/Emu/VFS.cpp @@ -33,7 +33,7 @@ struct vfs_manager vfs_directory root{}; }; -bool vfs::mount(std::string_view vpath, std::string_view path) +bool vfs::mount(std::string_view vpath, std::string_view path, bool create_dir) { if (vpath.empty()) { @@ -42,6 +42,12 @@ bool vfs::mount(std::string_view vpath, std::string_view path) return false; } + if (create_dir && !fs::is_dir(std::string(path)) && !fs::create_dir(std::string(path))) + { + vfs_log.error("Cannot create directory \"%s\"", path); + return false; + } + // Workaround g_fxo->need(); diff --git a/rpcs3/Emu/VFS.h b/rpcs3/Emu/VFS.h index bab790ca08..4c53c25640 100644 --- a/rpcs3/Emu/VFS.h +++ b/rpcs3/Emu/VFS.h @@ -10,7 +10,7 @@ struct vfs_directory; namespace vfs { // Mount VFS device - bool mount(std::string_view vpath, std::string_view path); + bool mount(std::string_view vpath, std::string_view path, bool create_dir = false); // Unmount VFS device bool unmount(std::string_view vpath);