Partial commit: FS

This commit is contained in:
Nekotekina 2016-02-02 00:50:22 +03:00
parent b85a68e8a1
commit 984aa44220
22 changed files with 0 additions and 1694 deletions

View File

@ -1,568 +0,0 @@
#include "stdafx.h"
#include "VFS.h"
#include "vfsDir.h"
#include "vfsFile.h"
#include "vfsDirBase.h"
#include "Emu/HDD/HDD.h"
#include "vfsDeviceLocalFile.h"
#include "Emu/System.h"
#include "Emu/state.h"
std::vector<std::string> simplify_path_blocks(const std::string& path)
{
// fmt::tolower() removed
std::vector<std::string> path_blocks = std::move(fmt::split(path, { "/", "\\" }));
for (s32 i = 0; i < path_blocks.size(); ++i)
{
if (path_blocks[i] == "." || (i > 0 && path_blocks[i].empty()))
{
path_blocks.erase(path_blocks.begin() + i);
i--;
}
else if (i > 0 && path_blocks[i] == "..")
{
path_blocks.erase(path_blocks.begin() + (i - 1), path_blocks.begin() + (i + 1));
i--;
}
}
return path_blocks;
}
std::string simplify_path(const std::string& path, bool is_dir, bool is_ps3)
{
std::vector<std::string> path_blocks = simplify_path_blocks(path);
if (path_blocks.empty())
return "";
std::string result = fmt::merge(path_blocks, "/");
#ifdef _WIN32
if (is_ps3)
#endif
{
result = "/" + result;
}
if (is_dir) result = result + "/";
return result;
}
VFS::~VFS()
{
UnMountAll();
}
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, true);
UnMount(simpl_ps3_path);
device->SetPath(simpl_ps3_path, simplify_path(local_path, true, false));
m_devices.push_back(device);
if (m_devices.size() > 1)
{
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(const std::string& ps3_path) const
{
// fmt::tolower removed
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, true);
for (u32 i = 0; i < m_devices.size(); ++i)
{
if (!strcmp(m_devices[i]->GetPs3Path().c_str(), simpl_ps3_path.c_str()))
{
delete m_devices[i];
m_devices.erase(m_devices.begin() +i);
return;
}
}
}
void VFS::UnMountAll()
{
for(u32 i=0; i<m_devices.size(); ++i)
{
delete m_devices[i];
}
m_devices.clear();
}
vfsFileBase* VFS::OpenFile(const std::string& ps3_path, u32 mode) const
{
std::string path;
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
if (vfsFileBase* res = dev->GetNewFileStream())
{
res->Open(path, mode);
return res;
}
}
return nullptr;
}
vfsDirBase* VFS::OpenDir(const std::string& ps3_path) const
{
std::string path;
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
if (vfsDirBase* res = dev->GetNewDirStream())
{
res->Open(path);
return res;
}
}
return nullptr;
}
bool VFS::CreateDir(const std::string& ps3_path) const
{
std::string path;
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
// return dev->create_dir(path);
return fs::create_dir(path);
}
return false;
}
bool VFS::CreatePath(const std::string& ps3_path) const
{
std::string path;
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
// return dev->create_path(path);
return fs::create_path(path);
}
return false;
}
bool VFS::RemoveFile(const std::string& ps3_path) const
{
std::string path;
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
// return dev->remove_file(path);
return fs::remove_file(path);
}
return false;
}
bool VFS::RemoveDir(const std::string& ps3_path) const
{
std::string path;
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
// return dev->remove_dir(path);
return fs::remove_dir(path);
}
return false;
}
void VFS::DeleteAll(const std::string& ps3_path) const
{
// Delete directory and all its contents recursively
for (const auto entry : vfsDir(ps3_path))
{
if (entry->name == "." || entry->name == "..")
{
continue;
}
if (entry->flags & DirEntry_TypeFile)
{
RemoveFile(ps3_path + "/" + entry->name);
}
if (entry->flags & DirEntry_TypeDir)
{
DeleteAll(ps3_path + "/" + entry->name);
}
}
RemoveDir(ps3_path);
}
u64 VFS::GetDirSize(const std::string& ps3_path) const
{
u64 result = 0;
for (const auto entry : vfsDir(ps3_path))
{
if (entry->name == "." || entry->name == "..")
{
continue;
}
if (entry->flags & DirEntry_TypeFile)
{
result += entry->size;
}
if (entry->flags & DirEntry_TypeDir)
{
result += GetDirSize(ps3_path + "/" + entry->name);
}
}
return result;
}
bool VFS::ExistsFile(const std::string& ps3_path) const
{
std::string path;
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
// return dev->is_file(path);
return fs::is_file(path);
}
return false;
}
bool VFS::ExistsDir(const std::string& ps3_path) const
{
std::string path;
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
// return dev->is_dir(path);
return fs::is_dir(path);
}
return false;
}
bool VFS::Exists(const std::string& ps3_path) const
{
std::string path;
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
// return dev->exists(path);
return fs::exists(path);
}
return false;
}
bool VFS::Rename(const std::string& ps3_path_from, const std::string& ps3_path_to) const
{
std::string path_from, path_to;
if (vfsDevice* dev = GetDevice(ps3_path_from, path_from))
{
if (vfsDevice* dev_ = GetDevice(ps3_path_to, path_to))
{
// return dev->rename(dev_, path_from, path_to);
return fs::rename(path_from, path_to);
}
}
return false;
}
bool VFS::CopyFile(const std::string& ps3_path_from, const std::string& ps3_path_to, bool overwrite) const
{
std::string path_from, path_to;
if (vfsDevice* dev = GetDevice(ps3_path_from, path_from))
{
if (vfsDevice* dev_ = GetDevice(ps3_path_to, path_to))
{
// return dev->copy_file(dev_, path_from, path_to, overwrite);
return fs::copy_file(path_from, path_to, overwrite);
}
}
return false;
}
bool VFS::TruncateFile(const std::string& ps3_path, u64 length) const
{
std::string path;
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
// return dev->truncate_file(path, length);
return fs::truncate_file(path, length);
}
return false;
}
vfsDevice* VFS::GetDevice(const std::string& ps3_path, std::string& path) const
{
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;
for (u32 i = 0; i < m_devices.size(); ++i)
{
std::vector<std::string> dev_ps3_path_blocks = simplify_path_blocks(m_devices[i]->GetPs3Path());
if (ps3_path_blocks.size() < dev_ps3_path_blocks.size())
continue;
size_t eq = 0;
for (; eq < dev_ps3_path_blocks.size(); ++eq)
{
if (strcmp(ps3_path_blocks[eq].c_str(), dev_ps3_path_blocks[eq].c_str()))
{
break;
}
}
if (eq > max_eq)
{
max_eq = eq;
max_i = i;
}
}
if (max_i < 0)
return nullptr;
path = m_devices[max_i]->GetLocalPath();
for (size_t i = max_eq; i < ps3_path_blocks.size(); i++)
{
path += "/" + ps3_path_blocks[i];
}
path = simplify_path(path, false, false);
return m_devices[max_i];
};
if (!ps3_path.size() || ps3_path[0] != '/')
{
return nullptr;
}
return try_get_device(GetLinked(ps3_path));
// What is it? cwd is real path, ps3_path is ps3 path, but GetLinked accepts ps3 path
//if (auto res = try_get_device(GetLinked(cwd + ps3_path)))
// return res;
}
vfsDevice* VFS::GetDeviceLocal(const std::string& local_path, std::string& path) const
{
int max_eq = -1;
int max_i = -1;
std::vector<std::string> local_path_blocks = simplify_path_blocks(local_path);
for (u32 i = 0; i < m_devices.size(); ++i)
{
std::vector<std::string> dev_local_path_blocks = simplify_path_blocks(m_devices[i]->GetLocalPath());
if (local_path_blocks.size() < dev_local_path_blocks.size())
continue;
int dev_blocks = dev_local_path_blocks.size();
bool prefix_equal = std::equal(
std::begin(dev_local_path_blocks),
std::end(dev_local_path_blocks),
std::begin(local_path_blocks),
[](const std::string& a, const std::string& b){ return strcmp(a.c_str(), b.c_str()) == 0; }
);
if (prefix_equal && dev_blocks > max_eq)
{
max_eq = dev_blocks;
max_i = i;
}
}
if (max_i < 0)
return nullptr;
path = m_devices[max_i]->GetPs3Path();
for (size_t i = max_eq; i < local_path_blocks.size(); i++)
{
path += "/" + local_path_blocks[i];
}
path = simplify_path(path, false, true);
return m_devices[max_i];
}
void VFS::Init(const std::string& path)
{
cwd = simplify_path(path, true, false);
UnMountAll();
std::vector<VFSManagerEntry> entries;
SaveLoadDevices(entries, true);
for(const VFSManagerEntry& entry : entries)
{
vfsDevice* dev;
switch(entry.device)
{
case vfsDevice_LocalFile:
dev = new vfsDeviceLocalFile();
break;
case vfsDevice_HDD:
dev = new vfsDeviceHDD(entry.device_path);
break;
default:
continue;
}
std::string mpath = entry.path;
// If no value assigned to SysEmulationDirPath in INI, use the path that with executable.
if (rpcs3::config.system.emulation_dir_path_enable.value())
{
fmt::Replace(mpath, "$(EmulatorDir)", rpcs3::config.system.emulation_dir_path.value());
}
else
{
fmt::Replace(mpath, "$(EmulatorDir)", fs::get_executable_dir());
}
fmt::Replace(mpath, "$(GameDir)", cwd);
Mount(entry.mount, mpath, dev);
}
Link("/app_home/", "/host_root/" + cwd);
}
void VFS::SaveLoadDevices(std::vector<VFSManagerEntry>& res, bool is_load)
{
int count = 0;
if (is_load)
{
count = rpcs3::config.vfs.count.value();
if (!count)
{
res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_hdd0/", "/dev_hdd0/");
res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_hdd1/", "/dev_hdd1/");
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, "", "/host_root/");
return;
}
res.resize(count);
}
else
{
count = (int)res.size();
rpcs3::config.vfs.count = count;
}
// Custom EmulationDir
if (rpcs3::config.system.emulation_dir_path_enable.value())
{
std::string dir = rpcs3::config.system.emulation_dir_path.value();
if (dir.empty())
{
rpcs3::config.system.emulation_dir_path = fs::get_executable_dir();
}
if (!fs::is_dir(dir))
{
LOG_ERROR(GENERAL, "Custom EmulationDir: directory '%s' not found", dir);
}
else
{
LOG_NOTICE(GENERAL, "Custom EmulationDir: $(EmulatorDir) bound to '%s'", dir);
}
}
for(int i=0; i<count; ++i)
{
rpcs3::config.vfs.add_entry(fmt::format("path[%d]", i), std::string{});
rpcs3::config.vfs.add_entry(fmt::format("device_path[%d]", i), std::string{});
rpcs3::config.vfs.add_entry(fmt::format("mount[%d]", i), std::string{});
rpcs3::config.vfs.add_entry(fmt::format("device[%d]", i), 0);
if (is_load)
{
res[i] = VFSManagerEntry();
res[i].path = rpcs3::config.vfs.get_entry_value<std::string>(fmt::format("path[%d]", i), std::string{});
res[i].device_path = rpcs3::config.vfs.get_entry_value<std::string>(fmt::format("device_path[%d]", i), std::string{});
res[i].mount = rpcs3::config.vfs.get_entry_value<std::string>(fmt::format("mount[%d]", i), std::string{});
res[i].device = (vfsDeviceType)rpcs3::config.vfs.get_entry_value<int>(fmt::format("device[%d]", i), 0);
}
else
{
rpcs3::config.vfs.set_entry_value(fmt::format("path[%d]", i), res[i].path);
rpcs3::config.vfs.set_entry_value(fmt::format("device_path[%d]", i), res[i].device_path);
rpcs3::config.vfs.set_entry_value(fmt::format("mount[%d]", i), res[i].mount);
rpcs3::config.vfs.set_entry_value(fmt::format("device[%d]", i), (int)res[i].device);
}
}
}

View File

@ -1,98 +0,0 @@
#pragma once
#include <map>
class vfsDevice;
struct vfsFileBase;
class vfsDirBase;
enum vfsDeviceType
{
vfsDevice_LocalFile,
vfsDevice_HDD,
};
static const char* vfsDeviceTypeNames[] =
{
"Local",
"HDD",
};
struct VFSManagerEntry
{
vfsDeviceType device;
std::string device_path;
std::string path;
std::string mount;
VFSManagerEntry()
: device(vfsDevice_LocalFile)
, device_path("")
, path("")
, mount("")
{
}
VFSManagerEntry(const vfsDeviceType& device, const std::string& path, const std::string& mount)
: device(device)
, device_path("")
, path(path)
, mount(mount)
{
}
};
std::vector<std::string> simplify_path_blocks(const std::string& path);
std::string simplify_path(const std::string& path, bool is_dir, bool is_ps3);
struct VFS
{
~VFS();
std::string cwd;
//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) const
{
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(const std::string& ps3_path) const;
vfsFileBase* OpenFile(const std::string& ps3_path, u32 mode) const;
vfsDirBase* OpenDir(const std::string& ps3_path) const;
bool CreateDir(const std::string& ps3_path) const;
bool CreatePath(const std::string& ps3_path) const;
bool RemoveFile(const std::string& ps3_path) const;
bool RemoveDir(const std::string& ps3_path) const;
void DeleteAll(const std::string& ps3_path) const;
u64 GetDirSize(const std::string& ps3_path) const;
bool ExistsFile(const std::string& ps3_path) const;
bool ExistsDir(const std::string& ps3_path) const;
bool Exists(const std::string& ps3_path) const;
bool Rename(const std::string& ps3_path_from, const std::string& ps3_path_to) const;
bool CopyFile(const std::string& ps3_path_from, const std::string& ps3_path_to, bool overwrite = true) const;
bool TruncateFile(const std::string& ps3_path, u64 length) const;
vfsDevice* GetDevice(const std::string& ps3_path, std::string& path) const;
vfsDevice* GetDeviceLocal(const std::string& local_path, std::string& path) const;
void Init(const std::string& path);
void SaveLoadDevices(std::vector<VFSManagerEntry>& res, bool is_load);
};

View File

@ -1,249 +0,0 @@
#include "stdafx.h"
#include "vfsDevice.h"
vfsDevice::vfsDevice(const std::string& ps3_path, const std::string& local_path)
: m_ps3_path(ps3_path)
, m_local_path(GetWinPath(local_path))
{
}
std::string vfsDevice::GetLocalPath() const
{
return m_local_path;
}
std::string vfsDevice::GetPs3Path() const
{
return m_ps3_path;
}
void vfsDevice::SetPath(const std::string& ps3_path, const std::string& local_path)
{
m_ps3_path = ps3_path;
m_local_path = local_path;
}
u32 vfsDevice::CmpPs3Path(const std::string& ps3_path)
{
const u32 lim = (u32)std::min(m_ps3_path.length(), ps3_path.length());
u32 ret = 0;
for(u32 i=0; i<lim; ++i, ++ret)
{
if(m_ps3_path[i] != ps3_path[i])
{
ret = 0;
break;
}
}
return ret;
}
u32 vfsDevice::CmpLocalPath(const std::string& local_path)
{
if(local_path.length() < m_local_path.length())
return 0;
#ifdef _WIN32
#define DL "\\"
#else
#define DL "/"
#endif
std::vector<std::string> arr0 = fmt::rSplit(m_local_path, DL);
std::vector<std::string> arr1 = fmt::rSplit(local_path, DL);
const u32 lim = (u32)std::min(arr0.size(), arr1.size());
u32 ret = 0;
for(u32 i=0; i<lim; ret += (u32)arr0[i++].size() + 1)
{
if(fmt::CmpNoCase(arr0[i],arr1[i]) != 0)
{
break;
}
}
return ret;
}
std::string vfsDevice::ErasePath(const std::string& path, u32 start_dir_count, u32 end_dir_count)
{
u32 from = 0;
u32 to = (u32)path.length() - 1;
for(uint i = 0, dir = 0; i < path.length(); ++i)
{
if(path[i] == '\\' || path[i] == '/' || i == path.length() - 1)
{
if(++dir == start_dir_count)
{
from = i;
break;
}
}
}
for(int i = (int)path.length() - 1, dir = 0; i >= 0; --i)
{
if(path[i] == '\\' || path[i] == '/' || i == 0)
{
if(dir++ == end_dir_count)
{
to = i;
break;
}
}
}
return path.substr(from, to - from);
}
std::string vfsDevice::GetRoot(const std::string& path)
{
//return fmt::ToUTF8(wxFileName(fmt::FromUTF8(path), wxPATH_UNIX).GetPath());
if(path.empty()) return "";
u32 first_dir = (u32)path.length() - 1;
for(int i = (int)path.length() - 1, dir = 0, li = (int)path.length() - 1; i >= 0 && dir < 2; --i)
{
if(path[i] == '\\' || path[i] == '/' || i == 0)
{
switch(dir++)
{
case 0:
first_dir = i;
break;
case 1:
if(!path.substr(i + 1, li - i).compare("USRDIR")) return path.substr(0, i + 1);
continue;
}
li = i - 1;
}
}
return path.substr(0, first_dir + 1);
}
std::string vfsDevice::GetRootPs3(const std::string& path)
{
if(path.empty()) return "";
static const std::string home = "/dev_hdd0/game/";
u32 last_dir = 0;
u32 first_dir = (u32)path.length() - 1;
for(int i = (int)path.length() - 1, dir = 0; i >= 0; --i)
{
if(path[i] == '\\' || path[i] == '/' || i == 0)
{
switch(dir++)
{
case 1:
if(path.substr(i + 1, last_dir - i - 1) == "USRDIR") return "";
break;
case 2:
return GetPs3Path(home + path.substr(i + 1, last_dir - i - 1));
}
last_dir = i;
}
}
return GetPs3Path(home + path.substr(0, last_dir - 1));
}
std::string vfsDevice::GetWinPath(const std::string& p, bool is_dir)
{
if(p.empty()) return "";
std::string ret;
bool is_ls = false;
for(u32 i=0; i<p.length(); ++i)
{
if(p[i] == '/' || p[i] == '\\')
{
if(!is_ls)
{
ret += '/';
is_ls = true;
}
continue;
}
is_ls = false;
ret += p[i];
}
if(is_dir && ret[ret.length() - 1] != '/' && ret[ret.length() - 1] != '\\') ret += '/'; // ???
return ret;
}
std::string vfsDevice::GetWinPath(const std::string& l, const std::string& r)
{
if(l.empty()) return GetWinPath(r, false);
if(r.empty()) return GetWinPath(l);
return GetWinPath(l + '/' + r, false);
}
std::string vfsDevice::GetPs3Path(const std::string& p, bool is_dir)
{
if(p.empty()) return "";
std::string ret;
bool is_ls = false;
for(u32 i=0; i<p.length(); ++i)
{
if(p[i] == L'/' || p[i] == L'\\')
{
if(!is_ls)
{
ret += '/';
is_ls = true;
}
continue;
}
is_ls = false;
ret += p[i];
}
if(ret[0] != '/') ret = '/' + ret;
if(is_dir && ret[ret.length() - 1] != '/') ret += '/';
return ret;
}
std::string vfsDevice::GetPs3Path(const std::string& l, const std::string& r)
{
if(l.empty()) return GetPs3Path(r, false);
if(r.empty()) return GetPs3Path(l);
return GetPs3Path(l + '/' + r, false);
}
void vfsDevice::Lock() const
{
m_mtx_lock.lock();
}
void vfsDevice::Unlock() const
{
m_mtx_lock.unlock();
}
bool vfsDevice::TryLock() const
{
return m_mtx_lock.try_lock();
}

View File

@ -1,55 +0,0 @@
#pragma once
struct vfsFileBase;
class vfsDirBase;
class vfsDevice
{
std::string m_ps3_path;
std::string m_local_path;
mutable std::mutex m_mtx_lock;
public:
vfsDevice(const std::string& ps3_path, const std::string& local_path);
vfsDevice() {}
virtual ~vfsDevice() {}
virtual vfsFileBase* GetNewFileStream()=0;
virtual vfsDirBase* GetNewDirStream()=0;
std::string GetLocalPath() const;
std::string GetPs3Path() const;
void SetPath(const std::string& ps3_path, const std::string& local_path);
u32 CmpPs3Path(const std::string& ps3_path);
u32 CmpLocalPath(const std::string& local_path);
static std::string ErasePath(const std::string& local_path, u32 start_dir_count, u32 end_dir_count);
static std::string GetRoot(const std::string& local_path);
static std::string GetRootPs3(const std::string& local_path);
static std::string GetWinPath(const std::string& p, bool is_dir = true);
static std::string GetWinPath(const std::string& l, const std::string& r);
static std::string GetPs3Path(const std::string& p, bool is_dir = true);
static std::string GetPs3Path(const std::string& l, const std::string& r);
void Lock() const;
void Unlock() const;
bool TryLock() const;
};
class vfsDeviceLocker
{
vfsDevice& m_device;
public:
vfsDeviceLocker(vfsDevice& device) : m_device(device)
{
m_device.Lock();
}
~vfsDeviceLocker()
{
m_device.Unlock();
}
};

View File

@ -1,14 +0,0 @@
#include "stdafx.h"
#include "vfsDeviceLocalFile.h"
#include "vfsLocalFile.h"
#include "vfsLocalDir.h"
vfsFileBase* vfsDeviceLocalFile::GetNewFileStream()
{
return new vfsLocalFile(this);
}
vfsDirBase* vfsDeviceLocalFile::GetNewDirStream()
{
return new vfsLocalDir(this);
}

View File

@ -1,9 +0,0 @@
#pragma once
#include "vfsDevice.h"
class vfsDeviceLocalFile : public vfsDevice
{
public:
virtual vfsFileBase* GetNewFileStream() override;
virtual vfsDirBase* GetNewDirStream() override;
};

View File

@ -1,79 +0,0 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "vfsDevice.h"
#include "VFS.h"
#include "vfsDir.h"
vfsDir::vfsDir()
: vfsDirBase(nullptr)
, m_stream(nullptr)
{
// TODO: proper implementation
// m_stream is nullptr here. So open root until a proper dir is given
//Open("/");
}
vfsDir::vfsDir(const std::string& path)
: vfsDirBase(nullptr)
, m_stream(nullptr)
{
Open(path);
}
bool vfsDir::Open(const std::string& path)
{
Close();
m_stream.reset(Emu.GetVFS().OpenDir(path));
DirEntryInfo info;
m_cwd = simplify_path(Emu.GetVFS().GetLinked(0 && m_stream && m_stream->IsOpened() ? m_stream->GetPath() : path), true, true);
auto blocks = simplify_path_blocks(GetPath());
for (auto dev : Emu.GetVFS().m_devices)
{
auto dev_blocks = simplify_path_blocks(dev->GetPs3Path());
if (dev_blocks.size() < (blocks.size() + 1))
{
continue;
}
bool is_ok = true;
for (size_t i = 0; i < blocks.size(); ++i)
{
if (strcmp(dev_blocks[i].c_str(), blocks[i].c_str()))
{
is_ok = false;
break;
}
}
if (is_ok)
{
info.name = dev_blocks[blocks.size()];
m_entries.push_back(info);
}
}
if (m_stream && m_stream->IsOpened())
{
m_entries.insert(m_entries.begin(), m_stream->GetEntries().begin(), m_stream->GetEntries().end());
}
return !m_entries.empty();
}
void vfsDir::Close()
{
m_stream.reset();
}
bool vfsDir::IsOpened() const
{
return !m_entries.empty();
}

View File

@ -1,17 +0,0 @@
#pragma once
#include "vfsDirBase.h"
class vfsDir : public vfsDirBase
{
private:
std::shared_ptr<vfsDirBase> m_stream;
public:
vfsDir();
vfsDir(const std::string& path);
virtual bool Open(const std::string& path) override;
virtual bool IsOpened() const override;
virtual void Close() override;
//virtual std::string GetPath() const override;
};

View File

@ -1,59 +0,0 @@
#include "stdafx.h"
#include "vfsDirBase.h"
vfsDirBase::vfsDirBase(vfsDevice* device)
: m_pos(0)
, m_device(device)
{
}
vfsDirBase::~vfsDirBase()
{
}
bool vfsDirBase::Open(const std::string& path)
{
if (IsOpened())
{
Close();
}
m_pos = 0;
m_cwd += '/' + path;
return true;
}
bool vfsDirBase::IsOpened() const
{
return !m_cwd.empty();
}
const std::vector<DirEntryInfo>& vfsDirBase::GetEntries() const
{
return m_entries;
}
void vfsDirBase::Close()
{
m_cwd = "";
m_entries.clear();
}
std::string vfsDirBase::GetPath() const
{
return m_cwd;
}
const DirEntryInfo* vfsDirBase::Read()
{
if (m_pos >= m_entries.size())
return nullptr;
return &m_entries[m_pos++];
}
const DirEntryInfo* vfsDirBase::First()
{
m_pos = 0;
return Read();
}

View File

@ -1,106 +0,0 @@
#pragma once
class vfsDevice;
enum DirEntryFlags
{
DirEntry_TypeDir = 0x1,
DirEntry_TypeFile = 0x2,
DirEntry_TypeMask = 0x3,
DirEntry_PermWritable = 0x20,
DirEntry_PermReadable = 0x40,
DirEntry_PermExecutable = 0x80,
};
struct DirEntryInfo
{
std::string name;
u32 flags;
u64 size;
time_t create_time;
time_t access_time;
time_t modify_time;
DirEntryInfo()
: flags(0)
, size(0)
, create_time(0)
, access_time(0)
, modify_time(0)
{
}
};
class vfsDirBase
{
protected:
std::string m_cwd;
std::vector<DirEntryInfo> m_entries;
uint m_pos;
vfsDevice* m_device;
public:
vfsDirBase(vfsDevice* device);
virtual ~vfsDirBase();
virtual bool Open(const std::string& path);
virtual bool IsOpened() const;
virtual const std::vector<DirEntryInfo>& GetEntries() const;
virtual void Close();
virtual std::string GetPath() const;
virtual const DirEntryInfo* Read();
virtual const DirEntryInfo* First();
class iterator
{
vfsDirBase *parent;
const DirEntryInfo* data;
public:
iterator(vfsDirBase* parent)
: parent(parent)
, data(parent->First())
{
}
iterator(vfsDirBase* parent, const DirEntryInfo* data)
: parent(parent)
, data(data)
{
}
iterator& operator++()
{
data = parent->Read();
return *this;
}
iterator operator++(int)
{
const DirEntryInfo* olddata = data;
data = parent->Read();
return iterator(parent, olddata);
}
const DirEntryInfo* operator *()
{
return data;
}
bool operator !=(iterator other) const
{
return data != other.data;
}
};
iterator begin()
{
return iterator(this);
}
iterator end()
{
return iterator(this, nullptr);
}
};

View File

@ -1,62 +0,0 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "VFS.h"
#include "vfsFile.h"
vfsFile::vfsFile()
: vfsFileBase(nullptr)
, m_stream(nullptr)
{
}
vfsFile::vfsFile(const std::string& path, u32 mode)
: vfsFileBase(nullptr)
, m_stream(nullptr)
{
Open(path, mode);
}
bool vfsFile::Open(const std::string& path, u32 mode)
{
Close();
m_stream.reset(Emu.GetVFS().OpenFile(path, mode));
return m_stream && m_stream->IsOpened();
}
void vfsFile::Close()
{
m_stream.reset();
}
u64 vfsFile::GetSize() const
{
return m_stream->GetSize();
}
u64 vfsFile::Write(const void* src, u64 size)
{
return m_stream->Write(src, size);
}
u64 vfsFile::Read(void* dst, u64 size)
{
return m_stream->Read(dst, size);
}
u64 vfsFile::Seek(s64 offset, fs::seek_mode whence)
{
return m_stream->Seek(offset, whence);
}
u64 vfsFile::Tell() const
{
return m_stream->Tell();
}
bool vfsFile::IsOpened() const
{
return m_stream && m_stream->IsOpened();
}

View File

@ -1,26 +0,0 @@
#pragma once
#include "vfsFileBase.h"
class vfsFile : public vfsFileBase
{
private:
std::shared_ptr<vfsFileBase> m_stream;
public:
vfsFile();
vfsFile(const std::string& path, u32 mode = fom::read);
virtual bool Open(const std::string& path, u32 mode = fom::read) override;
virtual void Close() override;
virtual u64 GetSize() const override;
virtual u64 Write(const void* src, u64 size) override;
virtual u64 Read(void* dst, u64 size) override;
virtual u64 Seek(s64 offset, fs::seek_mode whence = fs::seek_set) override;
virtual u64 Tell() const override;
virtual bool IsOpened() const override;
};

View File

@ -1,37 +0,0 @@
#include "stdafx.h"
#include "vfsFileBase.h"
vfsFileBase::vfsFileBase(vfsDevice* device)
: vfsStream()
, m_device(device)
{
}
vfsFileBase::~vfsFileBase()
{
Close();
}
bool vfsFileBase::Open(const std::string& path, u32 mode)
{
m_path = path;
m_mode = mode;
return true;
}
void vfsFileBase::Close()
{
m_path = "";
vfsStream::Close();
}
std::string vfsFileBase::GetPath() const
{
return m_path;
}
u32 vfsFileBase::GetOpenMode() const
{
return m_mode;
}

View File

@ -1,24 +0,0 @@
#pragma once
#include "vfsStream.h"
class vfsDevice;
struct vfsFileBase : public vfsStream
{
protected:
std::string m_path;
u32 m_mode;
vfsDevice* m_device;
public:
vfsFileBase(vfsDevice* device);
virtual ~vfsFileBase() override;
virtual bool Open(const std::string& path, u32 mode);
virtual void Close() override;
virtual bool IsOpened() const override { return !m_path.empty(); }
std::string GetPath() const;
u32 GetOpenMode() const;
};

View File

@ -1,44 +0,0 @@
#include "stdafx.h"
#include "vfsDevice.h"
#include "vfsLocalDir.h"
vfsLocalDir::vfsLocalDir(vfsDevice* device) : vfsDirBase(device)
{
}
vfsLocalDir::~vfsLocalDir()
{
}
bool vfsLocalDir::Open(const std::string& path)
{
if (!vfsDirBase::Open(path) || !m_dir.open(path))
{
return false;
}
std::string name;
fs::stat_t file_info;
while (m_dir.read(name, file_info) && name.size())
{
m_entries.emplace_back();
DirEntryInfo& info = m_entries.back();
info.name = name;
info.flags |= file_info.is_directory ? DirEntry_TypeDir | DirEntry_PermExecutable : DirEntry_TypeFile;
info.flags |= file_info.is_writable ? DirEntry_PermWritable | DirEntry_PermReadable : DirEntry_PermReadable;
info.size = file_info.size;
info.access_time = file_info.atime;
info.modify_time = file_info.mtime;
info.create_time = file_info.ctime;
}
return true;
}
bool vfsLocalDir::IsOpened() const
{
return m_dir && vfsDirBase::IsOpened();
}

View File

@ -1,16 +0,0 @@
#pragma once
#include "vfsDirBase.h"
class vfsLocalDir : public vfsDirBase
{
private:
u32 m_pos;
fs::dir m_dir;
public:
vfsLocalDir(vfsDevice* device);
virtual ~vfsLocalDir();
virtual bool Open(const std::string& path) override;
virtual bool IsOpened() const override;
};

View File

@ -1,49 +0,0 @@
#include "stdafx.h"
#include "vfsLocalFile.h"
vfsLocalFile::vfsLocalFile(vfsDevice* device) : vfsFileBase(device)
{
}
bool vfsLocalFile::Open(const std::string& path, u32 mode)
{
Close();
return m_file.open(path, mode) && vfsFileBase::Open(path, mode);
}
void vfsLocalFile::Close()
{
m_file.close();
vfsFileBase::Close();
}
u64 vfsLocalFile::GetSize() const
{
return m_file.size();
}
u64 vfsLocalFile::Write(const void* src, u64 size)
{
return m_file.write(src, size);
}
u64 vfsLocalFile::Read(void* dst, u64 size)
{
return m_file.read(dst, size);
}
u64 vfsLocalFile::Seek(s64 offset, fs::seek_mode whence)
{
return m_file.seek(offset, whence);
}
u64 vfsLocalFile::Tell() const
{
return m_file.seek(0, fs::seek_cur);
}
bool vfsLocalFile::IsOpened() const
{
return m_file && vfsFileBase::IsOpened();
}

View File

@ -1,27 +0,0 @@
#pragma once
#include "vfsFileBase.h"
class vfsLocalFile : public vfsFileBase
{
private:
fs::file m_file;
public:
vfsLocalFile(vfsDevice* device);
virtual bool Open(const std::string& path, u32 mode = fom::read) override;
virtual void Close() override;
virtual u64 GetSize() const override;
virtual u64 Write(const void* src, u64 size) override;
virtual u64 Read(void* dst, u64 size) override;
virtual u64 Seek(s64 offset, fs::seek_mode whence = fs::seek_set) override;
virtual u64 Tell() const override;
virtual bool IsOpened() const override;
virtual const fs::file& GetFile() const { return m_file; }
};

View File

@ -1,2 +0,0 @@
#include "stdafx.h"
#include "vfsStream.h"

View File

@ -1,69 +0,0 @@
#pragma once
struct vfsStream
{
vfsStream() = default;
virtual ~vfsStream()
{
Close();
}
virtual void Close()
{
}
virtual u64 GetSize() const = 0;
virtual u64 Write(const void* src, u64 count) = 0;
template<typename T>
force_inline bool SWrite(const T& data, u64 count = sizeof(T))
{
return Write(&data, count) == count;
}
virtual u64 Read(void* dst, u64 count) = 0;
template<typename T>
force_inline bool SRead(T& data, u64 count = sizeof(T))
{
return Read(&data, count) == count;
}
template<typename T>
bool VWrite(const std::vector<T>& vec)
{
return IsOpened() && Write(vec.data(), vec.size() * sizeof(T)) == vec.size() * sizeof(T);
}
template<typename T>
std::vector<T> VRead()
{
std::vector<T> result;
if (IsOpened() == false)
{
return result;
}
result.resize(GetSize() / sizeof(T));
if (Seek(0) == -1 || Read(result.data(), result.size() * sizeof(T)) != result.size() * sizeof(T))
{
result.clear();
}
return result;
}
virtual u64 Seek(s64 offset, fs::seek_mode whence = fs::seek_set) = 0;
virtual u64 Tell() const = 0;
virtual bool Eof() const
{
return Tell() >= GetSize();
}
virtual bool IsOpened() const = 0;
};

View File

@ -1,29 +0,0 @@
#include "stdafx.h"
#include "Emu/Memory/Memory.h"
#include "vfsStreamMemory.h"
u64 vfsStreamMemory::Write(const void* src, u64 count)
{
assert(m_pos < m_size);
if (m_pos + count > m_size)
{
count = m_size - m_pos;
}
std::memcpy(vm::base(VM_CAST(m_addr + m_pos)), src, count);
m_pos += count;
return count;
}
u64 vfsStreamMemory::Read(void* dst, u64 count)
{
assert(m_pos < m_size);
if (m_pos + count > m_size)
{
count = m_size - m_pos;
}
std::memcpy(dst, vm::base(VM_CAST(m_addr + m_pos)), count);
m_pos += count;
return count;
}

View File

@ -1,55 +0,0 @@
#pragma once
#include "vfsStream.h"
class vfsStreamMemory : public vfsStream
{
u64 m_pos = 0;
u32 m_addr = 0;
u64 m_size = 0;
public:
vfsStreamMemory() = default;
vfsStreamMemory(u32 addr, u32 size = 0)
{
Open(addr, size);
}
void Open(u32 addr, u32 size = 0)
{
m_pos = 0;
m_addr = addr;
m_size = size ? size : 0x100000000ull - addr; // determine max possible size
}
virtual u64 GetSize() const override
{
return m_size;
}
virtual u64 Write(const void* src, u64 count) override;
virtual u64 Read(void* dst, u64 count) override;
virtual u64 Seek(s64 offset, fs::seek_mode whence) override
{
switch (whence)
{
case fs::seek_set: return m_pos = offset;
case fs::seek_cur: return m_pos += offset;
case fs::seek_end: return m_pos = m_size + offset;
}
throw EXCEPTION("Unknown seek_mode (0x%x)", whence);
}
virtual u64 Tell() const override
{
return m_pos;
}
virtual bool IsOpened() const override
{
return true;
}
};