1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2025-02-13 03:40:49 +00:00

Fix lv2_fs_object::name

Recreate path from actual decoded components.
This commit is contained in:
Nekotekina 2020-01-04 20:10:37 +03:00
parent 5534c9e27c
commit 28fb0d1741
3 changed files with 44 additions and 9 deletions
rpcs3/Emu

@ -199,8 +199,9 @@ error_code sys_fs_open(ppu_thread& ppu, vm::cptr<char> path, s32 flags, vm::ptr<
if (!path[0])
return CELL_ENOENT;
std::string processed_path;
const std::string_view vpath = path.get_ptr();
const std::string local_path = vfs::get(vpath);
const std::string local_path = vfs::get(vpath, nullptr, &processed_path);
if (vpath.find_first_not_of('/') == -1)
{
@ -369,7 +370,7 @@ error_code sys_fs_open(ppu_thread& ppu, vm::cptr<char> path, s32 flags, vm::ptr<
}
}
if (const u32 id = idm::make<lv2_fs_object, lv2_file>(path.get_ptr(), std::move(file), mode, flags))
if (const u32 id = idm::make<lv2_fs_object, lv2_file>(processed_path.c_str(), std::move(file), mode, flags))
{
*fd = id;
return CELL_OK;
@ -480,9 +481,12 @@ error_code sys_fs_opendir(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<u32> fd)
if (!path[0])
return CELL_ENOENT;
std::string processed_path;
std::vector<std::string> ext;
const std::string_view vpath = path.get_ptr();
const std::string local_path = vfs::get(vpath, &ext);
const std::string local_path = vfs::get(vpath, &ext, &processed_path);
processed_path += "/";
if (local_path.empty() && ext.empty())
{
@ -568,7 +572,7 @@ error_code sys_fs_opendir(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<u32> fd)
data.erase(last, data.end());
if (const u32 id = idm::make<lv2_fs_object, lv2_dir>(path.get_ptr(), std::move(data)))
if (const u32 id = idm::make<lv2_fs_object, lv2_dir>(processed_path.c_str(), std::move(data)))
{
*fd = id;
return CELL_OK;

@ -84,7 +84,7 @@ bool vfs::mount(std::string_view vpath, std::string_view path)
}
// Go back one level
list.resize(list.size() - 1);
list.pop_back();
continue;
}
@ -108,7 +108,7 @@ bool vfs::mount(std::string_view vpath, std::string_view path)
}
}
std::string vfs::get(std::string_view vpath, std::vector<std::string>* out_dir)
std::string vfs::get(std::string_view vpath, std::vector<std::string>* out_dir, std::string* out_path)
{
const auto table = g_fxo->get<vfs_manager>();
@ -127,6 +127,14 @@ std::string vfs::get(std::string_view vpath, std::vector<std::string>* out_dir)
vpath = ".";
}
// Fragments for out_path
std::vector<std::string_view> name_list;
if (out_path)
{
name_list.reserve(vpath.size() / 2);
}
for (std::vector<const vfs_directory*> list{&table->root};;)
{
// Skip one or more '/'
@ -196,14 +204,24 @@ std::string vfs::get(std::string_view vpath, std::vector<std::string>* out_dir)
}
// Go back one level
list.resize(list.size() - 1);
result.resize(result.size() - 1);
if (out_path)
{
name_list.pop_back();
}
list.pop_back();
result.pop_back();
continue;
}
const auto last = list.back();
list.push_back(nullptr);
if (out_path)
{
name_list.push_back(name);
}
result.push_back(name);
if (!last)
@ -225,6 +243,13 @@ std::string vfs::get(std::string_view vpath, std::vector<std::string>* out_dir)
}
// Handle /host_root (not escaped, not processed)
if (out_path)
{
*out_path = "/";
*out_path += fmt::merge(name_list, "/");
*out_path += vpath;
}
return std::string{vpath.substr(1)};
}
@ -240,6 +265,12 @@ std::string vfs::get(std::string_view vpath, std::vector<std::string>* out_dir)
}
// Escape and merge path fragments
if (out_path)
{
*out_path = "/";
*out_path += fmt::merge(name_list, "/");
}
return std::string{result_base} + vfs::escape(fmt::merge(result, "/"));
}

@ -10,7 +10,7 @@ namespace vfs
bool mount(std::string_view vpath, std::string_view path);
// Convert VFS path to fs path, optionally listing directories mounted in it
std::string get(std::string_view vpath, std::vector<std::string>* out_dir = nullptr);
std::string get(std::string_view vpath, std::vector<std::string>* out_dir = nullptr, std::string* out_path = nullptr);
// Escape VFS path by replacing non-portable characters with surrogates
std::string escape(std::string_view path, bool escape_slash = false);