VFS fixes

- using /app_home/ as local link
Implemented fmt::merge & fmt::tolower
This commit is contained in:
DHrpcs3 2014-11-30 13:18:17 +02:00
parent ebae8dad0a
commit a58c5f5a4c
5 changed files with 94 additions and 40 deletions

View File

@ -57,7 +57,7 @@ int fmt::CmpNoCase(const std::string& a, const std::string& b)
return std::equal(a.begin(),
a.end(),
b.begin(),
[](const char& a, const char& b){return tolower(a) == tolower(b); })
[](const char& a, const char& b){return ::tolower(a) == ::tolower(b); })
? 0 : -1;
}
}
@ -133,4 +133,35 @@ std::vector<std::string> fmt::split(const std::string& source, std::initializer_
}
return std::move(result);
}
std::string fmt::merge(std::vector<std::string> source, const std::string& separator)
{
std::string result;
for (auto &s : source)
{
result += s + separator;
}
return result;
}
std::string fmt::merge(std::initializer_list<std::vector<std::string>> sources, const std::string& separator)
{
std::string result;
for (auto &v : sources)
{
result += fmt::merge(v, separator);
}
return result;
}
std::string fmt::tolower(std::string source)
{
std::transform(source.begin(), source.end(), source.begin(), ::tolower);
return source;
}

View File

@ -194,4 +194,7 @@ namespace fmt{
std::vector<std::string> rSplit(const std::string& source, const std::string& delim);
std::vector<std::string> split(const std::string& source, std::initializer_list<std::string> separators, bool is_skip_empty = true);
std::string merge(std::vector<std::string> source, const std::string& separator);
std::string merge(std::initializer_list<std::vector<std::string>> sources, const std::string& separator);
std::string tolower(std::string source);
}

View File

@ -8,23 +8,9 @@
#undef CreateFile
int sort_devices(const void* _a, const void* _b)
{
const vfsDevice& a = **(const vfsDevice**)_a;
const vfsDevice& b = **(const vfsDevice**)_b;
if (a.GetPs3Path().length() > b.GetPs3Path().length()) return 1;
if (a.GetPs3Path().length() < b.GetPs3Path().length()) return -1;
return 0;
}
std::vector<std::string> simplify_path_blocks(const std::string& path)
{
std::string lower_path = path;
std::transform(lower_path.begin(), lower_path.end(), lower_path.begin(), ::tolower);
std::vector<std::string> path_blocks = std::move(fmt::split(lower_path, { "/", "\\" }));
std::vector<std::string> path_blocks = std::move(fmt::split(fmt::tolower(path), { "/", "\\" }));
for (size_t i = 0; i < path_blocks.size(); ++i)
{
@ -53,19 +39,11 @@ std::string simplify_path(const std::string& path, bool is_dir)
if (is_dir)
{
for (auto &dir : path_blocks)
{
result += dir + "/";
}
result = fmt::merge(path_blocks, "/");
}
else
{
for (size_t i = 0; i < path_blocks.size() - 1; ++i)
{
result += path_blocks[i] + "/";
}
result += path_blocks[path_blocks.size() - 1];
result = fmt::merge(std::vector<std::string>(path_blocks.begin(), path_blocks.end() - 1), "/") + path_blocks[path_blocks.size() - 1];
}
return result;
@ -76,12 +54,6 @@ VFS::~VFS()
UnMountAll();
}
std::string VFS::FindEntry(const std::string &path)
{
return path;
return cwd + "/" + path;
}
void VFS::Mount(const std::string& ps3_path, const std::string& local_path, vfsDevice* device)
{
std::string simpl_ps3_path = simplify_path(ps3_path, true);
@ -93,10 +65,43 @@ void VFS::Mount(const std::string& ps3_path, const std::string& local_path, vfsD
if (m_devices.size() > 1)
{
//std::qsort(m_devices.GetPtr(), m_devices.GetCount(), sizeof(vfsDevice*), sort_devices);
std::sort(m_devices.begin(), m_devices.end(), [](vfsDevice *a, vfsDevice *b) { return b->GetPs3Path().length() < a->GetPs3Path().length(); });
}
}
void VFS::Link(const std::string& mount_point, const std::string& ps3_path)
{
links[simplify_path_blocks(mount_point)] = simplify_path_blocks(ps3_path);
}
std::string VFS::GetLinked(std::string ps3_path) const
{
ps3_path = fmt::tolower(ps3_path);
auto path_blocks = fmt::split(ps3_path, { "/", "\\" });
for (auto link : links)
{
if (path_blocks.size() < link.first.size())
continue;
bool is_ok = true;
for (size_t i = 0; i < link.first.size(); ++i)
{
if (link.first[i] != path_blocks[i])
{
is_ok = false;
break;
}
}
if (is_ok)
return fmt::merge({ link.second, std::vector<std::string>(path_blocks.begin() + link.first.size(), path_blocks.end()) }, "/");
}
return ps3_path;
}
void VFS::UnMount(const std::string& ps3_path)
{
std::string simpl_ps3_path = simplify_path(ps3_path, true);
@ -285,8 +290,9 @@ bool VFS::RenameDir(const std::string& ps3_path_from, const std::string& ps3_pat
vfsDevice* VFS::GetDevice(const std::string& ps3_path, std::string& path) const
{
auto try_get_device = [this, &path](const std::vector<std::string>& ps3_path_blocks) -> vfsDevice*
auto try_get_device = [this, &path](const std::string& ps3_path) -> vfsDevice*
{
std::vector<std::string> ps3_path_blocks = simplify_path_blocks(ps3_path);
size_t max_eq = 0;
int max_i = -1;
@ -328,10 +334,10 @@ vfsDevice* VFS::GetDevice(const std::string& ps3_path, std::string& path) const
return m_devices[max_i];
};
if (auto res = try_get_device(simplify_path_blocks(ps3_path)))
if (auto res = try_get_device(GetLinked(ps3_path)))
return res;
if (auto res = try_get_device(simplify_path_blocks(cwd + ps3_path)))
if (auto res = try_get_device(GetLinked(cwd + ps3_path)))
return res;
return nullptr;
@ -415,6 +421,8 @@ void VFS::Init(const std::string& path)
fmt::Replace(mpath, "$(GameDir)", cwd);
Mount(entry.mount, mpath, dev);
}
Link("/app_home/", cwd);
}
void VFS::SaveLoadDevices(std::vector<VFSManagerEntry>& res, bool is_load)
@ -434,7 +442,6 @@ void VFS::SaveLoadDevices(std::vector<VFSManagerEntry>& res, bool is_load)
res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_flash/", "/dev_flash/");
res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_usb000/", "/dev_usb000/");
res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_usb000/", "/dev_usb/");
res.emplace_back(vfsDevice_LocalFile, "$(GameDir)", "/app_home/");
res.emplace_back(vfsDevice_LocalFile, "$(GameDir)/../", "/dev_bdvd/");
res.emplace_back(vfsDevice_LocalFile, "", "/host_root/");

View File

@ -1,4 +1,5 @@
#pragma once
#include <map>
class vfsDevice;
struct vfsFileBase;
@ -51,18 +52,30 @@ struct VFS
std::string cwd;
std::string FindEntry(const std::string &path);
//TODO: find out where these are supposed to be deleted or just make it shared_ptr
//and also make GetDevice and GetDeviceLocal return shared_ptr then.
// A vfsDevice will be deleted when they're unmounted or the VFS struct is destroyed.
// This will cause problems if other code stores the pointer returned by GetDevice/GetDeviceLocal
// and tries to use it after the device is unmounted.
std::vector<vfsDevice *> m_devices;
struct links_sorter
{
bool operator()(const std::vector<std::string>& a, const std::vector<std::string>& b)
{
return b.size() < a.size();
}
};
std::map<std::vector<std::string>, std::vector<std::string>, links_sorter> links;
void Mount(const std::string& ps3_path, const std::string& local_path, vfsDevice* device);
void Link(const std::string& mount_point, const std::string& ps3_path);
void UnMount(const std::string& ps3_path);
void UnMountAll();
std::string GetLinked(std::string ps3_path) const;
vfsFileBase* OpenFile(const std::string& ps3_path, vfsOpenMode mode) const;
vfsDirBase* OpenDir(const std::string& ps3_path) const;
bool CreateFile(const std::string& ps3_path) const;

View File

@ -29,7 +29,7 @@ bool vfsDir::Open(const std::string& path)
DirEntryInfo info;
m_cwd = simplify_path(0 && m_stream && m_stream->IsOpened() ? m_stream->GetPath() : path, true);
m_cwd = simplify_path(Emu.GetVFS().GetLinked(0 && m_stream && m_stream->IsOpened() ? m_stream->GetPath() : path), true);
auto blocks = simplify_path_blocks(GetPath());