Further implemented sys_fs_get_mount_info() and sys_fs_get_mount_info_size()

This commit is contained in:
brian218 2022-11-13 22:15:46 +08:00 committed by Megamouse
parent 16098c38c8
commit 13ca1a7f09
3 changed files with 132 additions and 89 deletions

View File

@ -20,17 +20,32 @@
LOG_CHANNEL(sys_fs);
lv2_fs_mount_point g_mp_sys_dev_root;
lv2_fs_mount_point g_mp_sys_no_device;
lv2_fs_mount_point g_mp_sys_dev_hdd0{"/dev_hdd0", 512, 0x24FAEA98};
lv2_fs_mount_point g_mp_sys_dev_hdd1{"/dev_hdd1", 512, 0x3FFFF8, 32768, lv2_mp_flag::no_uid_gid + lv2_mp_flag::cache};
lv2_fs_mount_point g_mp_sys_dev_usb{"", 512, 0x100, 4096, lv2_mp_flag::no_uid_gid};
lv2_fs_mount_point g_mp_sys_dev_bdvd{"", 2048, 0x4D955, 65536, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid};
lv2_fs_mount_point g_mp_sys_dev_dvd{"", 2048, 0x100, 32768, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid};
lv2_fs_mount_point g_mp_sys_host_root{"", 512, 0x100, 512, lv2_mp_flag::strict_get_block_size + lv2_mp_flag::no_uid_gid};
lv2_fs_mount_point g_mp_sys_dev_flash{"", 512, 0x63E00, 8192, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid};
lv2_fs_mount_point g_mp_sys_dev_flash2{"", 512, 0x8000, 8192, lv2_mp_flag::no_uid_gid}; // TODO confirm
lv2_fs_mount_point g_mp_sys_dev_flash3{"", 512, 0x400, 8192, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid}; // TODO confirm
lv2_fs_mount_point g_mp_sys_dev_root{"/", "CELL_FS_ADMINFS", "CELL_FS_ADMINFS:"};
lv2_fs_mount_point g_mp_sys_app_home{"/app_home", "CELL_FS_DUMMYFS", "CELL_FS_DUMMY:", 512, 0x100, 512, lv2_mp_flag::strict_get_block_size + lv2_mp_flag::no_uid_gid};
lv2_fs_mount_point g_mp_sys_host_root{"/host_root", "CELL_FS_DUMMYFS", "CELL_FS_DUMMY:/", 512, 0x100, 512, lv2_mp_flag::strict_get_block_size + lv2_mp_flag::no_uid_gid};
lv2_fs_mount_point g_mp_sys_dev_flash{"/dev_flash", "CELL_FS_FAT", "CELL_FS_IOS:BUILTIN_FLSH1", 512, 0x63E00, 8192, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid};
lv2_fs_mount_point g_mp_sys_dev_flash2{"/dev_flash2", "CELL_FS_FAT", "CELL_FS_IOS:BUILTIN_FLSH2", 512, 0x8000, 8192, lv2_mp_flag::no_uid_gid}; // TODO confirm
lv2_fs_mount_point g_mp_sys_dev_flash3{"/dev_flash3", "CELL_FS_FAT", "CELL_FS_IOS:BUILTIN_FLSH3", 512, 0x400, 8192, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid}; // TODO confirm
lv2_fs_mount_point g_mp_sys_dev_hdd0{"/dev_hdd0", "CELL_FS_UFS", "CELL_FS_UTILITY:HDD0", 512, 0x24FAEA98};
lv2_fs_mount_point g_mp_sys_dev_hdd1{"/dev_hdd1", "CELL_FS_FAT", "CELL_FS_UTILITY:HDD1", 512, 0x3FFFF8, 32768, lv2_mp_flag::no_uid_gid + lv2_mp_flag::cache};
lv2_fs_mount_point g_mp_sys_dev_bdvd{"/dev_bdvd", "CELL_FS_ISO9660", "CELL_FS_IOS:PATA0_BDVD_DRIVE", 2048, 0x4D955, 65536, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid};
lv2_fs_mount_point g_mp_sys_dev_dvd{"/dev_ps2disc", "CELL_FS_ISO9660", "CELL_FS_IOS:PATA0_BDVD_DRIVE", 2048, 0x100, 32768, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid};
lv2_fs_mount_point g_mp_sys_dev_usb{"/dev_usb", "CELL_FS_FAT", "CELL_FS_IOS:USB_MASS_STORAGE", 512, 0x100, 4096, lv2_mp_flag::no_uid_gid};
constexpr lv2_fs_mount_point* mp_array[]
{
&g_mp_sys_dev_root,
&g_mp_sys_app_home,
&g_mp_sys_host_root,
&g_mp_sys_dev_flash,
&g_mp_sys_dev_flash2,
&g_mp_sys_dev_flash3,
&g_mp_sys_dev_hdd0,
&g_mp_sys_dev_hdd1,
&g_mp_sys_dev_bdvd,
&g_mp_sys_dev_dvd,
&g_mp_sys_dev_usb,
};
template<>
void fmt_class_string<lv2_file_type>::format(std::string& out, u64 arg)
@ -178,72 +193,65 @@ 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)
return &g_mp_sys_dev_hdd0;
if (mp_name == "dev_hdd1"sv)
return &g_mp_sys_dev_hdd1;
if (mp_name.starts_with("dev_usb"sv))
return &g_mp_sys_dev_usb;
if (mp_name == "dev_bdvd"sv)
return &g_mp_sys_dev_bdvd;
if (mp_name == "dev_ps2disc"sv)
return &g_mp_sys_dev_dvd;
if (mp_name == "app_home"sv && filename.data() != Emu.argv[0].data())
return lv2_fs_object::get_mp(Emu.argv[0]);
if (mp_name == "host_root"sv)
return &g_mp_sys_host_root;
if (mp_name == "dev_flash"sv)
return &g_mp_sys_dev_flash;
if (mp_name == "dev_flash2"sv)
return &g_mp_sys_dev_flash2;
if (mp_name == "dev_flash3"sv)
return &g_mp_sys_dev_flash3;
// Default
if (mp_name == "dev_hdd0"sv)
return &g_mp_sys_dev_hdd0;
}
if (mp_name == "dev_hdd1"sv)
return &g_mp_sys_dev_hdd1;
if (mp_name.starts_with("dev_usb"sv))
return &g_mp_sys_dev_usb;
if (mp_name == "dev_bdvd"sv)
return &g_mp_sys_dev_bdvd;
if (mp_name == "dev_ps2disc"sv)
return &g_mp_sys_dev_dvd;
if (mp_name == "app_home"sv)
return &g_mp_sys_app_home;
if (mp_name == "host_root"sv)
return &g_mp_sys_host_root;
if (mp_name == "dev_flash"sv)
return &g_mp_sys_dev_flash;
if (mp_name == "dev_flash2"sv)
return &g_mp_sys_dev_flash2;
if (mp_name == "dev_flash3"sv)
return &g_mp_sys_dev_flash3;
// Default fallback
return &g_mp_sys_dev_root;
return &g_mp_sys_no_device;
}
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 g_cfg.vfs.host_root ? "/" : std::string();
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
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)
return g_cfg_vfs.get(g_cfg_vfs.app_home, rpcs3::utils::get_emu_dir());
if (mp_name == "host_root"sv)
return g_cfg.vfs.host_root ? "/" : std::string();
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 fallback
return {};
}
s32 lv2_fs_object::get_mount_count()
{
return std::count_if(std::begin(mp_array), std::end(mp_array), [](lv2_fs_mount_point* mp){return mp != &g_mp_sys_dev_usb && mp->is_mounted == 1U;}) + std::popcount(g_mp_sys_dev_usb.is_mounted);
}
lv2_fs_object::lv2_fs_object(utils::serial& ar, bool)
: name(ar)
, mp(get_mp(name.data()))
@ -2932,54 +2940,62 @@ error_code sys_fs_truncate2(ppu_thread&, u32 fd, u64 size)
error_code sys_fs_get_mount_info_size(ppu_thread&, vm::ptr<u64> len)
{
sys_fs.todo("sys_fs_get_mount_info_size(len=*0x%x)", len);
sys_fs.trace("sys_fs_get_mount_info_size(len=*0x%x)", len);
if (!len)
{
return CELL_EFAULT;
}
*len = 0x9;
*len = lv2_fs_object::get_mount_count();
return CELL_OK;
}
error_code sys_fs_get_mount_info(ppu_thread&, vm::ptr<CellFsMountInfo> info, u32 len, vm::ptr<u64> out_len)
{
sys_fs.todo("sys_fs_get_mount_info(info=*0x%x, len=0x%x, out_len=*0x%x)", info, len, out_len);
sys_fs.trace("sys_fs_get_mount_info(info=*0x%x, len=0x%x, out_len=*0x%x)", info, len, out_len);
if (!out_len)
if (!info || !out_len)
{
return CELL_EFAULT;
}
// TODO there is a case where 'something' happens if !info or len == 0
if (!info || len == 0)
{
sys_fs.todo("sys_fs_get_mount_info special case TODO");
}
const u32 max_len = std::min<u32>(len, 9);
const u32 max_len = std::min<u32>(len, lv2_fs_object::get_mount_count());
*out_len = max_len;
struct mount_info
{
std::string_view path, filesystem, dev_name;
std::string path, filesystem, dev_name;
be_t<u32> unk1 = 0, unk2 = 0, unk3 = 0, unk4 = 0, unk5 = 0;
};
static constexpr std::array<mount_info, 9> data
std::vector<mount_info> data;
for (auto mp : mp_array)
{
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:"},
mount_info{.path = "/host_root", .filesystem = "CELL_FS_DUMMY", .dev_name = "CELL_FS_DUMMY:"},
mount_info{.path = "/dev_flash", .filesystem = "CELL_FS_FAT", .dev_name = "CELL_FS_IOS:BUILTIN_FLSH1:", .unk5 = 0x10000000},
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"},
};
if (mp->is_mounted == 0U)
continue;
if (mp == &g_mp_sys_dev_usb)
{
for (int i = 0; i < 8; i++)
{
if ((mp->is_mounted >> i) & 1U)
{
data.push_back(mount_info{.path = fmt::format("%s%03d", mp->root, i), .filesystem = mp->file_system.data(), .dev_name = fmt::format("%s%03d", mp->device, i)});
}
}
}
else if (mp == &g_mp_sys_dev_root || mp == &g_mp_sys_dev_flash)
{
data.push_back(mount_info{.path = mp->root.data(), .filesystem = mp->file_system.data(), .dev_name = mp->device.data(), .unk5 = 0x10000000});
}
else
{
data.push_back(mount_info{.path = mp->root.data(), .filesystem = mp->file_system.data(), .dev_name = mp->device.data()});
}
}
for (u32 i = 0; i < max_len; info++, i++)
{
@ -2992,7 +3008,7 @@ error_code sys_fs_get_mount_info(ppu_thread&, vm::ptr<CellFsMountInfo> info, u32
return CELL_OK;
}
error_code sys_fs_newfs(ppu_thread& ppu, vm::cptr<char> dev_name, vm::cptr<char> file_system, s32 unk1, vm::cptr<char> str1)
error_code sys_fs_newfs(ppu_thread&, vm::cptr<char> dev_name, vm::cptr<char> file_system, s32 unk1, vm::cptr<char> str1)
{
sys_fs.todo("sys_fs_newfs(dev_name=%s, file_system=%s, unk1=0x%x, str1=%s)", dev_name, file_system, unk1, str1);
@ -3032,6 +3048,12 @@ error_code sys_fs_mount(ppu_thread&, vm::cptr<char> dev_name, vm::cptr<char> fil
auto vfs_mount = [&vpath = vpath, &filesystem = filesystem, &mp = mp](std::string mount_path)
{
const std::string local_path = vfs::get(vpath);
if (!local_path.empty())
{
sys_fs.error("\"%s\" has already been mounted to \"%s\"", vpath, local_path);
return false;
}
if (!mount_path.ends_with('/'))
mount_path += '/';
if (!fs::is_dir(mount_path) && !fs::create_dir(mount_path))
@ -3097,6 +3119,11 @@ error_code sys_fs_unmount(ppu_thread&, vm::cptr<char> path, s32 unk1, s32 unk2)
auto vfs_unmount = [&vpath = vpath]()
{
const std::string local_path = vfs::get(vpath);
if (local_path.empty())
{
sys_fs.error("\"%s\" is not mounted!", vpath);
return false;
}
if (fs::is_file(local_path))
{
if (fs::remove_file(local_path))

View File

@ -148,16 +148,20 @@ enum class lv2_file_type
struct lv2_fs_mount_point
{
const std::string_view root;
const std::string_view file_system;
const std::string_view device;
const u32 sector_size = 512;
const u64 sector_count = 256;
const u32 block_size = 4096;
const bs_t<lv2_mp_flag> flags{};
u8 is_mounted = 0U;
mutable std::recursive_mutex mutex;
};
extern lv2_fs_mount_point g_mp_sys_dev_hdd0;
extern lv2_fs_mount_point g_mp_sys_dev_hdd1;
extern lv2_fs_mount_point g_mp_sys_dev_usb;
struct lv2_fs_object
{
@ -190,6 +194,7 @@ public:
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 s32 get_mount_count();
static std::array<char, 0x420> get_name(std::string_view filename)
{
@ -617,8 +622,8 @@ error_code sys_fs_lsn_write(ppu_thread& ppu, u32 fd, vm::cptr<void>, u64);
error_code sys_fs_mapped_allocate(ppu_thread& ppu, u32 fd, u64, vm::pptr<void> out_ptr);
error_code sys_fs_mapped_free(ppu_thread& ppu, u32 fd, vm::ptr<void> ptr);
error_code sys_fs_truncate2(ppu_thread& ppu, u32 fd, u64 size);
error_code sys_fs_newfs(ppu_thread& ppu, vm::cptr<char> dev_name, vm::cptr<char> file_system, s32 unk1, vm::cptr<char> str1);
error_code sys_fs_mount(ppu_thread& ppu, vm::cptr<char> dev_name, vm::cptr<char> file_system, vm::cptr<char> path, s32 unk1, s32 prot, s32 unk3, vm::cptr<char> str1, u32 str_len);
error_code sys_fs_newfs(ppu_thread&, vm::cptr<char> dev_name, vm::cptr<char> file_system, s32 unk1, vm::cptr<char> str1);
error_code sys_fs_mount(ppu_thread&, vm::cptr<char> dev_name, vm::cptr<char> file_system, vm::cptr<char> path, s32 unk1, s32 prot, s32 unk3, vm::cptr<char> str1, u32 str_len);
error_code sys_fs_unmount(ppu_thread&, vm::cptr<char> path, s32 unk1, s32 unk2);
error_code sys_fs_get_mount_info_size(ppu_thread& ppu, vm::ptr<u64> len);
error_code sys_fs_get_mount_info(ppu_thread& ppu, vm::ptr<CellFsMountInfo> info, u32 len, vm::ptr<u64> out_len);
error_code sys_fs_get_mount_info_size(ppu_thread&, vm::ptr<u64> len);
error_code sys_fs_get_mount_info(ppu_thread&, vm::ptr<CellFsMountInfo> info, u32 len, vm::ptr<u64> out_len);

View File

@ -73,6 +73,11 @@ bool vfs::mount(std::string_view vpath, std::string_view path, bool is_dir)
list.back()->path += '/';
if (!is_dir && list.back()->path.ends_with('/'))
vfs_log.error("File mounted with trailing /.");
const auto mp = lv2_fs_object::get_mp(vpath_backup);
if (mp == &g_mp_sys_dev_usb)
mp->is_mounted |= (1U << vpath_backup.back() - '0');
else
mp->is_mounted = 1U;
vfs_log.notice("Mounted path \"%s\" to \"%s\"", vpath_backup, list.back()->path);
return true;
}
@ -180,6 +185,12 @@ bool vfs::unmount(std::string_view vpath)
};
unmount_children(table.root, 0);
const auto mp = lv2_fs_object::get_mp(vpath);
if (mp == &g_mp_sys_dev_usb)
mp->is_mounted &= ~(1U << vpath.back() - '0');
else
mp->is_mounted = 0U;
return true;
}