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

View File

@ -199,8 +199,9 @@ error_code sys_fs_open(ppu_thread& ppu, vm::cptr<char> path, s32 flags, vm::ptr<
if (!path[0]) if (!path[0])
return CELL_ENOENT; return CELL_ENOENT;
std::string processed_path;
const std::string_view vpath = path.get_ptr(); 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) 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; *fd = id;
return CELL_OK; 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]) if (!path[0])
return CELL_ENOENT; return CELL_ENOENT;
std::string processed_path;
std::vector<std::string> ext; std::vector<std::string> ext;
const std::string_view vpath = path.get_ptr(); 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()) 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()); 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; *fd = id;
return CELL_OK; return CELL_OK;

View File

@ -84,7 +84,7 @@ bool vfs::mount(std::string_view vpath, std::string_view path)
} }
// Go back one level // Go back one level
list.resize(list.size() - 1); list.pop_back();
continue; 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>(); 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 = "."; 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};;) for (std::vector<const vfs_directory*> list{&table->root};;)
{ {
// Skip one or more '/' // 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 // Go back one level
list.resize(list.size() - 1); if (out_path)
result.resize(result.size() - 1); {
name_list.pop_back();
}
list.pop_back();
result.pop_back();
continue; continue;
} }
const auto last = list.back(); const auto last = list.back();
list.push_back(nullptr); list.push_back(nullptr);
if (out_path)
{
name_list.push_back(name);
}
result.push_back(name); result.push_back(name);
if (!last) 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) // 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)}; 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 // 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, "/")); return std::string{result_base} + vfs::escape(fmt::merge(result, "/"));
} }

View File

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