mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 03:25:16 +00:00
sys_fs: Implemented mount_info_map to keep proper track of mounted devices
This commit is contained in:
parent
43184a271f
commit
e9281843bf
2 changed files with 201 additions and 122 deletions
|
@ -32,36 +32,6 @@ lv2_fs_mount_point g_mp_sys_app_home{"/app_home", "CELL_FS_DUMMYFS", "CELL_FS_DU
|
|||
lv2_fs_mount_point g_mp_sys_dev_root{"/", "CELL_FS_ADMINFS", "CELL_FS_ADMINFS:", 512, 0x100, 512, lv2_mp_flag::read_only + lv2_mp_flag::strict_get_block_size + lv2_mp_flag::no_uid_gid, &g_mp_sys_app_home};
|
||||
lv2_fs_mount_point g_mp_sys_no_device{};
|
||||
|
||||
struct mount_point_reset
|
||||
{
|
||||
SAVESTATE_INIT_POS(49);
|
||||
|
||||
mount_point_reset() = default;
|
||||
|
||||
mount_point_reset(const mount_point_reset&) = delete;
|
||||
|
||||
mount_point_reset& operator =(const mount_point_reset&) = delete;
|
||||
|
||||
~mount_point_reset()
|
||||
{
|
||||
for (auto mp = &g_mp_sys_dev_root; mp; mp = mp->next)
|
||||
{
|
||||
if (mp == &g_mp_sys_dev_usb)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
lv2_fs_object::vfs_unmount(fmt::format("%s%03d", mp->root, i));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lv2_fs_object::vfs_unmount(mp->root);
|
||||
}
|
||||
}
|
||||
g_fxo->get<mount_point_reset>(); // Register destructor
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
void fmt_class_string<lv2_file_type>::format(std::string& out, u64 arg)
|
||||
{
|
||||
|
@ -151,6 +121,94 @@ bool verify_mself(const fs::file& mself_file)
|
|||
return true;
|
||||
}
|
||||
|
||||
lv2_fs_mount_info_map::lv2_fs_mount_info_map()
|
||||
{
|
||||
for (auto mp = &g_mp_sys_dev_root; mp; mp = mp->next) // Scan and keep track of pre-mounted devices
|
||||
{
|
||||
if (mp == &g_mp_sys_dev_usb)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (!vfs::get(fmt::format("%s%03d", mp->root, i)).empty())
|
||||
{
|
||||
add(fmt::format("%s%03d", mp->root, i), mp, fmt::format("%s%03d", mp->device, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mp == &g_mp_sys_dev_root || !vfs::get(mp->root).empty())
|
||||
{
|
||||
add(std::string(mp->root), mp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lv2_fs_mount_info_map::~lv2_fs_mount_info_map()
|
||||
{
|
||||
for (const auto& [path, info] : map)
|
||||
lv2_fs_object::vfs_unmount(path);
|
||||
map.clear();
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
bool lv2_fs_mount_info_map::add(Args&&... args)
|
||||
{
|
||||
return map.try_emplace(std::forward<Args>(args)...).second;
|
||||
}
|
||||
|
||||
bool lv2_fs_mount_info_map::remove(std::string_view path)
|
||||
{
|
||||
if (const auto iterator = map.find(path); iterator != map.end())
|
||||
{
|
||||
map.erase(iterator);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const lv2_fs_mount_info& lv2_fs_mount_info_map::lookup(std::string_view path) const
|
||||
{
|
||||
if (const auto iterator = map.find(path); iterator != map.end())
|
||||
return iterator->second;
|
||||
return mount_info_no_device;
|
||||
}
|
||||
|
||||
u64 lv2_fs_mount_info_map::get_all(CellFsMountInfo* info, u64 len) const
|
||||
{
|
||||
if (!info)
|
||||
return map.size();
|
||||
|
||||
struct mount_info
|
||||
{
|
||||
const std::string_view path, filesystem, dev_name;
|
||||
const be_t<u32> unk1 = 0, unk2 = 0, unk3 = 0, unk4 = 0, unk5 = 0;
|
||||
};
|
||||
|
||||
u64 count = 0;
|
||||
|
||||
auto push_info = [&](mount_info&& data)
|
||||
{
|
||||
if (count >= len)
|
||||
return;
|
||||
|
||||
strcpy_trunc(info->mount_path, data.path);
|
||||
strcpy_trunc(info->filesystem, data.filesystem);
|
||||
strcpy_trunc(info->dev_name, data.dev_name);
|
||||
std::memcpy(&info->unk1, &data.unk1, sizeof(be_t<u32>) * 5);
|
||||
|
||||
info++, count++;
|
||||
};
|
||||
|
||||
for (const auto& [path, mi] : map)
|
||||
{
|
||||
if (mi == &g_mp_sys_dev_root || mi == &g_mp_sys_dev_flash)
|
||||
push_info(mount_info{.path = path, .filesystem = mi.file_system, .dev_name = mi.device, .unk5 = 0x10000000});
|
||||
else
|
||||
push_info(mount_info{.path = path, .filesystem = mi.file_system, .dev_name = mi.device});
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
std::string_view lv2_fs_object::get_device_root(std::string_view filename)
|
||||
{
|
||||
std::string_view mp_name, vpath = filename;
|
||||
|
@ -223,9 +281,9 @@ lv2_fs_mount_point* lv2_fs_object::get_mp(std::string_view filename, std::string
|
|||
const auto pos = mp->root.find_first_not_of('/');
|
||||
const auto mp_root = pos != umax ? mp->root.substr(pos) : mp->root;
|
||||
const auto& device_alias_check = !is_path && (
|
||||
(mp == &g_mp_sys_dev_hdd0 && filename == "CELL_FS_IOS:PATA0_HDD_DRIVE"sv) ||
|
||||
(mp == &g_mp_sys_dev_hdd1 && filename == "CELL_FS_IOS:PATA1_HDD_DRIVE"sv) ||
|
||||
(mp == &g_mp_sys_dev_flash2 && filename == "CELL_FS_IOS:BUILTIN_FLASH"sv)); // TODO confirm
|
||||
(mp == &g_mp_sys_dev_hdd0 && mp_name == "CELL_FS_IOS:PATA0_HDD_DRIVE"sv) ||
|
||||
(mp == &g_mp_sys_dev_hdd1 && mp_name == "CELL_FS_IOS:PATA1_HDD_DRIVE"sv) ||
|
||||
(mp == &g_mp_sys_dev_flash2 && mp_name == "CELL_FS_IOS:BUILTIN_FLASH"sv)); // TODO confirm
|
||||
|
||||
if (mp == &g_mp_sys_dev_usb)
|
||||
{
|
||||
|
@ -253,7 +311,9 @@ lv2_fs_mount_point* lv2_fs_object::get_mp(std::string_view filename, std::string
|
|||
|
||||
if (vfs_path)
|
||||
{
|
||||
if (result == &g_mp_sys_dev_hdd0)
|
||||
if (is_cell_fs_path)
|
||||
*vfs_path = vfs::get(filename);
|
||||
else if (result == &g_mp_sys_dev_hdd0)
|
||||
*vfs_path = g_cfg_vfs.get(g_cfg_vfs.dev_hdd0, rpcs3::utils::get_emu_dir());
|
||||
else if (result == &g_mp_sys_dev_hdd1)
|
||||
*vfs_path = g_cfg_vfs.get(g_cfg_vfs.dev_hdd1, rpcs3::utils::get_emu_dir());
|
||||
|
@ -276,7 +336,7 @@ lv2_fs_mount_point* lv2_fs_object::get_mp(std::string_view filename, std::string
|
|||
else
|
||||
*vfs_path = {};
|
||||
|
||||
if (is_path && !vfs_path->empty())
|
||||
if (is_path && !is_cell_fs_path && !vfs_path->empty())
|
||||
vfs_path->append(filename.substr(mp_name.size() + 1)); // substr: remove leading "/mp_name"
|
||||
}
|
||||
|
||||
|
@ -2101,29 +2161,33 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr<void> _arg, u32
|
|||
std::string_view vpath{ arg->name.get_ptr(), arg->name_size };
|
||||
|
||||
// Trim trailing '\0'
|
||||
if (auto trim_pos = vpath.find('\0'); trim_pos != vpath.npos)
|
||||
if (const auto trim_pos = vpath.find('\0'); trim_pos != umax)
|
||||
{
|
||||
vpath.remove_suffix(vpath.size() - trim_pos);
|
||||
}
|
||||
|
||||
if (!vpath.starts_with("/dev_usb"sv))
|
||||
{
|
||||
arg->out_code = CELL_ENOTSUP;
|
||||
return {CELL_ENOTSUP, vpath};
|
||||
}
|
||||
|
||||
if (vfs::get(vpath).empty())
|
||||
{
|
||||
arg->out_code = CELL_ENOTMOUNTED;
|
||||
return {CELL_ENOTMOUNTED, vpath};
|
||||
}
|
||||
|
||||
const cfg::device_info device = g_cfg_vfs.get_device(g_cfg_vfs.dev_usb, vpath);
|
||||
const auto& mi = g_fxo->get<lv2_fs_mount_info_map>().lookup(vpath);
|
||||
const auto num_pos = mi.device.find_first_of("0123456789");
|
||||
|
||||
if (mi != &g_mp_sys_dev_usb || num_pos == umax)
|
||||
{
|
||||
arg->out_code = CELL_ENOTSUP;
|
||||
return {CELL_ENOTSUP, vpath};
|
||||
}
|
||||
|
||||
const std::string device_path = fmt::format("%s%s", mi->root, mi.device.substr(num_pos));
|
||||
const cfg::device_info device = g_cfg_vfs.get_device(g_cfg_vfs.dev_usb, device_path);
|
||||
std::tie(arg->vendorID, arg->productID) = device.get_usb_ids();
|
||||
|
||||
arg->out_code = CELL_OK;
|
||||
|
||||
sys_fs.trace("sys_fs_fcntl(0xc0000015): found device '%s' (vid=0x%x, pid=0x%x)", vpath, arg->vendorID, arg->productID);
|
||||
sys_fs.trace("sys_fs_fcntl(0xc0000015): found device '%s' (vid=0x%x, pid=0x%x)", device_path, arg->vendorID, arg->productID);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -2157,24 +2221,28 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr<void> _arg, u32
|
|||
std::string_view vpath{ arg->name.get_ptr(), arg->name_size };
|
||||
|
||||
// Trim trailing '\0'
|
||||
if (auto trim_pos = vpath.find('\0'); trim_pos != vpath.npos)
|
||||
if (const auto trim_pos = vpath.find('\0'); trim_pos != umax)
|
||||
{
|
||||
vpath.remove_suffix(vpath.size() - trim_pos);
|
||||
}
|
||||
|
||||
if (!vpath.starts_with("/dev_usb"sv))
|
||||
{
|
||||
arg->out_code = CELL_ENOTSUP;
|
||||
return {CELL_ENOTSUP, vpath};
|
||||
}
|
||||
|
||||
if (vfs::get(vpath).empty())
|
||||
{
|
||||
arg->out_code = CELL_ENOTMOUNTED;
|
||||
return {CELL_ENOTMOUNTED, vpath};
|
||||
}
|
||||
|
||||
const cfg::device_info device = g_cfg_vfs.get_device(g_cfg_vfs.dev_usb, vpath);
|
||||
const auto& mi = g_fxo->get<lv2_fs_mount_info_map>().lookup(vpath);
|
||||
const auto num_pos = mi.device.find_first_of("0123456789");
|
||||
|
||||
if (mi != &g_mp_sys_dev_usb || num_pos == umax)
|
||||
{
|
||||
arg->out_code = CELL_ENOTSUP;
|
||||
return {CELL_ENOTSUP, vpath};
|
||||
}
|
||||
|
||||
const std::string device_path = fmt::format("%s%s", mi->root, mi.device.substr(num_pos));
|
||||
const cfg::device_info device = g_cfg_vfs.get_device(g_cfg_vfs.dev_usb, device_path);
|
||||
std::tie(arg->vendorID, arg->productID) = device.get_usb_ids();
|
||||
|
||||
// Serial needs to be encoded to utf-16 BE
|
||||
|
@ -2183,7 +2251,7 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr<void> _arg, u32
|
|||
|
||||
arg->out_code = CELL_OK;
|
||||
|
||||
sys_fs.trace("sys_fs_fcntl(0xc000001c): found device '%s' (vid=0x%x, pid=0x%x, serial=%s)", vpath, arg->vendorID, arg->productID, device.serial);
|
||||
sys_fs.trace("sys_fs_fcntl(0xc000001c): found device '%s' (vid=0x%x, pid=0x%x, serial=%s)", device_path, arg->vendorID, arg->productID, device.serial);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -2994,27 +3062,7 @@ error_code sys_fs_get_mount_info_size(ppu_thread&, vm::ptr<u64> len)
|
|||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
u64 count = 0;
|
||||
|
||||
for (auto mp = &g_mp_sys_dev_root; mp; mp = mp->next)
|
||||
{
|
||||
if (mp == &g_mp_sys_dev_usb)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (!vfs::get(fmt::format("%s%03d", mp->root, i)).empty())
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mp == &g_mp_sys_dev_root || !vfs::get(mp->root).empty())
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
*len = count;
|
||||
*len = g_fxo->get<lv2_fs_mount_info_map>().get_all();
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -3028,53 +3076,7 @@ error_code sys_fs_get_mount_info(ppu_thread&, vm::ptr<CellFsMountInfo> info, u64
|
|||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
struct mount_info
|
||||
{
|
||||
const std::string_view path, filesystem, dev_name;
|
||||
const be_t<u32> unk1 = 0, unk2 = 0, unk3 = 0, unk4 = 0, unk5 = 0;
|
||||
};
|
||||
|
||||
u64 count = 0;
|
||||
|
||||
auto push_info = [&](mount_info&& data)
|
||||
{
|
||||
if (count >= len)
|
||||
return;
|
||||
|
||||
strcpy_trunc(info->mount_path, data.path);
|
||||
strcpy_trunc(info->filesystem, data.filesystem);
|
||||
strcpy_trunc(info->dev_name, data.dev_name);
|
||||
std::memcpy(&info->unk1, &data.unk1, sizeof(be_t<u32>) * 5);
|
||||
|
||||
info++, count++;
|
||||
};
|
||||
|
||||
for (auto mp = &g_mp_sys_dev_root; mp; mp = mp->next)
|
||||
{
|
||||
if (mp == &g_mp_sys_dev_usb)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (!vfs::get(fmt::format("%s%03d", mp->root, i)).empty())
|
||||
{
|
||||
push_info(mount_info{.path = fmt::format("%s%03d", mp->root, i), .filesystem = mp->file_system, .dev_name = fmt::format("%s%03d", mp->device, i)});
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mp == &g_mp_sys_dev_root || !vfs::get(mp->root).empty())
|
||||
{
|
||||
if (mp == &g_mp_sys_dev_root || mp == &g_mp_sys_dev_flash)
|
||||
{
|
||||
push_info(mount_info{.path = mp->root, .filesystem = mp->file_system, .dev_name = mp->device, .unk5 = 0x10000000});
|
||||
}
|
||||
else
|
||||
{
|
||||
push_info(mount_info{.path = mp->root, .filesystem = mp->file_system, .dev_name = mp->device});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*out_len = count;
|
||||
*out_len = g_fxo->get<lv2_fs_mount_info_map>().get_all(info.get_ptr(), len);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -3192,7 +3194,7 @@ error_code sys_fs_mount(ppu_thread& ppu, vm::cptr<char> dev_name, vm::cptr<char>
|
|||
{
|
||||
const u64 file_size = mp_src->sector_size; // One sector's size is enough for VSH's simplefs check
|
||||
simplefs_file.trunc(file_size);
|
||||
sys_fs.notice("Created a simplefs file of size 0x%x at \"%s\"", file_size, vfs_path);
|
||||
sys_fs.notice("Created a simplefs file at \"%s\"", vfs_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3218,6 +3220,8 @@ error_code sys_fs_mount(ppu_thread& ppu, vm::cptr<char> dev_name, vm::cptr<char>
|
|||
return CELL_EIO;
|
||||
}
|
||||
|
||||
g_fxo->get<lv2_fs_mount_info_map>().add(std::string(vpath), mp_src, device_name, filesystem, prot);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -3248,5 +3252,7 @@ error_code sys_fs_unmount(ppu_thread& ppu, vm::cptr<char> path, s32 unk1, s32 un
|
|||
if (!lv2_fs_object::vfs_unmount(vpath))
|
||||
return {CELL_ENOTMOUNTED, vpath};
|
||||
|
||||
g_fxo->get<lv2_fs_mount_info_map>().remove(vpath);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
|
|
@ -160,6 +160,79 @@ struct lv2_fs_mount_point
|
|||
};
|
||||
|
||||
extern lv2_fs_mount_point g_mp_sys_dev_hdd0;
|
||||
extern lv2_fs_mount_point g_mp_sys_no_device;
|
||||
|
||||
struct lv2_fs_mount_info
|
||||
{
|
||||
lv2_fs_mount_point* const mp;
|
||||
const std::string device;
|
||||
const std::string file_system;
|
||||
const bool read_only;
|
||||
|
||||
lv2_fs_mount_info(lv2_fs_mount_point* mp = nullptr, std::string_view device = {}, std::string_view file_system = {}, bool read_only = false)
|
||||
: mp(mp ? mp : &g_mp_sys_no_device)
|
||||
, device(device.empty() ? this->mp->device : device)
|
||||
, file_system(file_system.empty() ? this->mp->file_system : file_system)
|
||||
, read_only((this->mp->flags & lv2_mp_flag::read_only) || read_only)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr bool operator==(const lv2_fs_mount_info& rhs) const noexcept
|
||||
{
|
||||
return this == &rhs;
|
||||
}
|
||||
constexpr bool operator==(lv2_fs_mount_point* const& rhs) const noexcept
|
||||
{
|
||||
return mp == rhs;
|
||||
}
|
||||
constexpr const lv2_fs_mount_point* operator->() const noexcept
|
||||
{
|
||||
return mp;
|
||||
}
|
||||
};
|
||||
|
||||
struct CellFsMountInfo; // Forward Declaration
|
||||
|
||||
struct lv2_fs_mount_info_map
|
||||
{
|
||||
public:
|
||||
SAVESTATE_INIT_POS(49);
|
||||
|
||||
lv2_fs_mount_info_map();
|
||||
lv2_fs_mount_info_map(const lv2_fs_mount_info_map&) = delete;
|
||||
lv2_fs_mount_info_map& operator=(const lv2_fs_mount_info_map&) = delete;
|
||||
~lv2_fs_mount_info_map();
|
||||
|
||||
// Forwarding arguments to map.try_emplace(): refer to the constructor of lv2_fs_mount_info
|
||||
template <typename... Args>
|
||||
bool add(Args&&... args);
|
||||
bool remove(std::string_view path);
|
||||
const lv2_fs_mount_info& lookup(std::string_view path) const;
|
||||
u64 get_all(CellFsMountInfo* info = nullptr, u64 len = 0) const;
|
||||
|
||||
private:
|
||||
struct string_hash
|
||||
{
|
||||
using hash_type = std::hash<std::string_view>;
|
||||
using is_transparent = void;
|
||||
|
||||
std::size_t operator()(const char* str) const
|
||||
{
|
||||
return hash_type{}(str);
|
||||
}
|
||||
std::size_t operator()(std::string_view str) const
|
||||
{
|
||||
return hash_type{}(str);
|
||||
}
|
||||
std::size_t operator()(std::string const& str) const
|
||||
{
|
||||
return hash_type{}(str);
|
||||
}
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, lv2_fs_mount_info, string_hash, std::equal_to<>> map;
|
||||
lv2_fs_mount_info mount_info_no_device;
|
||||
};
|
||||
|
||||
struct lv2_fs_object
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue