mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-26 04:32:35 +01:00
Partial commit: FS
This commit is contained in:
parent
b85a68e8a1
commit
984aa44220
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
};
|
@ -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();
|
||||
}
|
@ -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();
|
||||
}
|
||||
};
|
@ -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);
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
#include "vfsDevice.h"
|
||||
|
||||
class vfsDeviceLocalFile : public vfsDevice
|
||||
{
|
||||
public:
|
||||
virtual vfsFileBase* GetNewFileStream() override;
|
||||
virtual vfsDirBase* GetNewDirStream() override;
|
||||
};
|
@ -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();
|
||||
}
|
@ -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;
|
||||
};
|
@ -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();
|
||||
}
|
@ -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);
|
||||
}
|
||||
};
|
@ -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();
|
||||
}
|
@ -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;
|
||||
};
|
@ -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;
|
||||
}
|
@ -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;
|
||||
};
|
@ -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();
|
||||
}
|
@ -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;
|
||||
};
|
@ -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();
|
||||
}
|
@ -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; }
|
||||
};
|
@ -1,2 +0,0 @@
|
||||
#include "stdafx.h"
|
||||
#include "vfsStream.h"
|
@ -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;
|
||||
};
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user