mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-04 05:51:27 +12:00
vfsLocalDir, rFile routines improved
This commit is contained in:
parent
2798827066
commit
d032bc5691
9 changed files with 334 additions and 667 deletions
|
@ -5,23 +5,37 @@
|
||||||
#include <wx/file.h>
|
#include <wx/file.h>
|
||||||
#include <wx/filename.h>
|
#include <wx/filename.h>
|
||||||
#include "rFile.h"
|
#include "rFile.h"
|
||||||
#include "errno.h"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
// Maybe in StrFmt?
|
#define GET_API_ERROR static_cast<u64>(GetLastError())
|
||||||
std::wstring ConvertUTF8ToWString(const std::string &source)
|
|
||||||
|
std::unique_ptr<wchar_t> ConvertUTF8ToWChar(const std::string& source)
|
||||||
{
|
{
|
||||||
int len = (int)source.size();
|
const size_t length = source.size() + 1; // size + null terminator
|
||||||
int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, NULL, 0);
|
|
||||||
std::wstring str;
|
const int size = length && length <= INT_MAX ? static_cast<int>(length) : throw std::length_error(__FUNCTION__);
|
||||||
str.resize(size);
|
|
||||||
if (size > 0) {
|
std::unique_ptr<wchar_t> buffer(new wchar_t[length]); // allocate buffer assuming that length is the max possible size
|
||||||
MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, &str[0], size);
|
|
||||||
|
if (!MultiByteToWideChar(CP_UTF8, 0, source.c_str(), size, buffer.get(), size))
|
||||||
|
{
|
||||||
|
LOG_ERROR(GENERAL, "ConvertUTF8ToWChar(source='%s') failed: 0x%llx", source.c_str(), GET_API_ERROR);
|
||||||
}
|
}
|
||||||
return str;
|
|
||||||
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time_t to_time_t(const FILETIME& ft)
|
||||||
|
{
|
||||||
|
ULARGE_INTEGER v;
|
||||||
|
v.LowPart = ft.dwLowDateTime;
|
||||||
|
v.HighPart = ft.dwHighDateTime;
|
||||||
|
|
||||||
|
return v.QuadPart / 10000000ULL - 11644473600ULL;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -30,62 +44,79 @@ std::wstring ConvertUTF8ToWString(const std::string &source)
|
||||||
#else
|
#else
|
||||||
#include <sys/sendfile.h>
|
#include <sys/sendfile.h>
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#include "errno.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define GET_API_ERROR static_cast<u64>(GetLastError())
|
|
||||||
#else
|
|
||||||
#define GET_API_ERROR static_cast<u64>(errno)
|
#define GET_API_ERROR static_cast<u64>(errno)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool getFileInfo(const char *path, FileInfo *fileInfo)
|
bool get_file_info(const std::string& path, FileInfo& info)
|
||||||
{
|
{
|
||||||
// TODO: Expand relative paths?
|
// TODO: Expand relative paths?
|
||||||
fileInfo->fullName = path;
|
info.fullName = path;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
WIN32_FILE_ATTRIBUTE_DATA attrs;
|
WIN32_FILE_ATTRIBUTE_DATA attrs;
|
||||||
if (!GetFileAttributesExW(ConvertUTF8ToWString(path).c_str(), GetFileExInfoStandard, &attrs)) {
|
if (!GetFileAttributesExW(ConvertUTF8ToWChar(path).get(), GetFileExInfoStandard, &attrs))
|
||||||
fileInfo->size = 0;
|
{
|
||||||
fileInfo->isDirectory = false;
|
info.exists = false;
|
||||||
fileInfo->isWritable = false;
|
info.isDirectory = false;
|
||||||
fileInfo->exists = false;
|
info.isWritable = false;
|
||||||
|
info.size = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
fileInfo->size = (uint64_t)attrs.nFileSizeLow | ((uint64_t)attrs.nFileSizeHigh << 32);
|
|
||||||
fileInfo->isDirectory = (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
info.exists = true;
|
||||||
fileInfo->isWritable = (attrs.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0;
|
info.isDirectory = (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||||
fileInfo->exists = true;
|
info.isWritable = (attrs.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0;
|
||||||
|
info.size = (uint64_t)attrs.nFileSizeLow | ((uint64_t)attrs.nFileSizeHigh << 32);
|
||||||
|
info.atime = to_time_t(attrs.ftLastAccessTime);
|
||||||
|
info.mtime = to_time_t(attrs.ftLastWriteTime);
|
||||||
|
info.ctime = to_time_t(attrs.ftCreationTime);
|
||||||
#else
|
#else
|
||||||
struct stat64 file_info;
|
struct stat64 file_info;
|
||||||
int result = stat64(path, &file_info);
|
if (stat64(path, &file_info) < 0)
|
||||||
|
{
|
||||||
if (result < 0) {
|
info.exists = false;
|
||||||
fileInfo->size = 0;
|
info.isDirectory = false;
|
||||||
fileInfo->isDirectory = false;
|
info.isWritable = false;
|
||||||
fileInfo->isWritable = false;
|
info.size = 0;
|
||||||
fileInfo->exists = false;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileInfo->isDirectory = S_ISDIR(file_info.st_mode);
|
info.exists = true;
|
||||||
fileInfo->isWritable = false;
|
info.isDirectory = S_ISDIR(file_info.st_mode);
|
||||||
fileInfo->size = file_info.st_size;
|
info.isWritable = file_info.st_mode & 0200; // HACK: approximation
|
||||||
fileInfo->exists = true;
|
info.size = file_info.st_size;
|
||||||
// HACK: approximation
|
info.atime = file_info.st_atime;
|
||||||
if (file_info.st_mode & 0200)
|
info.mtime = file_info.st_mtime;
|
||||||
fileInfo->isWritable = true;
|
info.ctime = file_info.st_ctime;
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rIsDir(const std::string &filename) {
|
bool rIsDir(const std::string& dir)
|
||||||
FileInfo info;
|
{
|
||||||
getFileInfo(filename.c_str(), &info);
|
#ifdef _WIN32
|
||||||
return info.isDirectory;
|
DWORD attrs;
|
||||||
|
if ((attrs = GetFileAttributesW(ConvertUTF8ToWChar(dir).get())) == INVALID_FILE_ATTRIBUTES)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (attrs & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||||
|
#else
|
||||||
|
struct stat64 file_info;
|
||||||
|
if (stat64(path, &file_info) < 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_ISDIR(file_info.st_mode);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rMkdir(const std::string &dir)
|
bool rMkdir(const std::string& dir)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return !_mkdir(dir.c_str());
|
return !_mkdir(dir.c_str());
|
||||||
|
@ -94,7 +125,7 @@ bool rMkdir(const std::string &dir)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rMkpath(const std::string &path)
|
bool rMkpath(const std::string& path)
|
||||||
{
|
{
|
||||||
size_t start=0, pos;
|
size_t start=0, pos;
|
||||||
std::string dir;
|
std::string dir;
|
||||||
|
@ -121,10 +152,10 @@ bool rMkpath(const std::string &path)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rRmdir(const std::string &dir)
|
bool rRmdir(const std::string& dir)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (!RemoveDirectory(ConvertUTF8ToWString(dir).c_str()))
|
if (!RemoveDirectory(ConvertUTF8ToWChar(dir).get()))
|
||||||
#else
|
#else
|
||||||
if (rmdir(dir.c_str()))
|
if (rmdir(dir.c_str()))
|
||||||
#endif
|
#endif
|
||||||
|
@ -136,11 +167,11 @@ bool rRmdir(const std::string &dir)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rRename(const std::string &from, const std::string &to)
|
bool rRename(const std::string& from, const std::string& to)
|
||||||
{
|
{
|
||||||
// TODO: Deal with case-sensitivity
|
// TODO: Deal with case-sensitivity
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (!MoveFile(ConvertUTF8ToWString(from).c_str(), ConvertUTF8ToWString(to).c_str()))
|
if (!MoveFile(ConvertUTF8ToWChar(from).get(), ConvertUTF8ToWChar(to).get()))
|
||||||
#else
|
#else
|
||||||
if (rename(from.c_str(), to.c_str()))
|
if (rename(from.c_str(), to.c_str()))
|
||||||
#endif
|
#endif
|
||||||
|
@ -191,7 +222,7 @@ int OSCopyFile(const char* source, const char* destination, bool overwrite)
|
||||||
bool rCopy(const std::string& from, const std::string& to, bool overwrite)
|
bool rCopy(const std::string& from, const std::string& to, bool overwrite)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (!CopyFile(ConvertUTF8ToWString(from).c_str(), ConvertUTF8ToWString(to).c_str(), !overwrite))
|
if (!CopyFile(ConvertUTF8ToWChar(from).get(), ConvertUTF8ToWChar(to).get(), !overwrite))
|
||||||
#else
|
#else
|
||||||
if (OSCopyFile(from.c_str(), to.c_str(), overwrite))
|
if (OSCopyFile(from.c_str(), to.c_str(), overwrite))
|
||||||
#endif
|
#endif
|
||||||
|
@ -203,21 +234,20 @@ bool rCopy(const std::string& from, const std::string& to, bool overwrite)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rExists(const std::string &file)
|
bool rExists(const std::string& file)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
std::wstring wstr = ConvertUTF8ToWString(file);
|
return GetFileAttributes(ConvertUTF8ToWChar(file).get()) != 0xFFFFFFFF;
|
||||||
return GetFileAttributes(wstr.c_str()) != 0xFFFFFFFF;
|
|
||||||
#else
|
#else
|
||||||
struct stat buffer;
|
struct stat buffer;
|
||||||
return (stat (file.c_str(), &buffer) == 0);
|
return stat(file.c_str(), &buffer) == 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rRemoveFile(const std::string &file)
|
bool rRemoveFile(const std::string& file)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (!DeleteFile(ConvertUTF8ToWString(file).c_str()))
|
if (!DeleteFile(ConvertUTF8ToWChar(file).get()))
|
||||||
#else
|
#else
|
||||||
if (unlink(file.c_str()))
|
if (unlink(file.c_str()))
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,16 +1,20 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
struct FileInfo {
|
struct FileInfo
|
||||||
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string fullName;
|
std::string fullName;
|
||||||
bool exists;
|
bool exists;
|
||||||
bool isDirectory;
|
bool isDirectory;
|
||||||
bool isWritable;
|
bool isWritable;
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
|
time_t atime;
|
||||||
|
time_t mtime;
|
||||||
|
time_t ctime;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool getFileInfo(const char *path, FileInfo *fileInfo);
|
bool get_file_info(const std::string& path, FileInfo& fileInfo);
|
||||||
bool rIsDir(const std::string& filename);
|
bool rIsDir(const std::string& dir);
|
||||||
bool rRmdir(const std::string& dir);
|
bool rRmdir(const std::string& dir);
|
||||||
bool rMkdir(const std::string& dir);
|
bool rMkdir(const std::string& dir);
|
||||||
bool rMkpath(const std::string& path);
|
bool rMkpath(const std::string& path);
|
||||||
|
|
|
@ -16,12 +16,14 @@ struct DirEntryInfo
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
|
u64 size;
|
||||||
time_t create_time;
|
time_t create_time;
|
||||||
time_t access_time;
|
time_t access_time;
|
||||||
time_t modify_time;
|
time_t modify_time;
|
||||||
|
|
||||||
DirEntryInfo()
|
DirEntryInfo()
|
||||||
: flags(0)
|
: flags(0)
|
||||||
|
, size(0)
|
||||||
, create_time(0)
|
, create_time(0)
|
||||||
, access_time(0)
|
, access_time(0)
|
||||||
, modify_time(0)
|
, modify_time(0)
|
||||||
|
|
|
@ -12,30 +12,29 @@ vfsLocalDir::~vfsLocalDir()
|
||||||
|
|
||||||
bool vfsLocalDir::Open(const std::string& path)
|
bool vfsLocalDir::Open(const std::string& path)
|
||||||
{
|
{
|
||||||
if(!vfsDirBase::Open(path))
|
if (!vfsDirBase::Open(path) || !dir.Open(path))
|
||||||
return false;
|
{
|
||||||
|
|
||||||
if(!dir.Open(path))
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
for(bool is_ok = dir.GetFirst(&name); is_ok; is_ok = dir.GetNext(&name))
|
|
||||||
|
for (bool is_ok = dir.GetFirst(&name); is_ok; is_ok = dir.GetNext(&name))
|
||||||
{
|
{
|
||||||
std::string dir_path = path + "/" + name;
|
FileInfo file_info;
|
||||||
|
get_file_info(path + "/" + name, file_info);
|
||||||
|
|
||||||
m_entries.emplace_back();
|
m_entries.emplace_back();
|
||||||
// TODO: Use same info structure as fileinfo?
|
|
||||||
DirEntryInfo& info = m_entries.back();
|
DirEntryInfo& info = m_entries.back();
|
||||||
|
|
||||||
info.name = name;
|
info.name = name;
|
||||||
|
info.flags |= file_info.isDirectory ? DirEntry_TypeDir | DirEntry_PermExecutable : DirEntry_TypeFile;
|
||||||
FileInfo fileinfo;
|
info.flags |= file_info.isWritable ? DirEntry_PermWritable | DirEntry_PermReadable : DirEntry_PermReadable;
|
||||||
getFileInfo(dir_path.c_str(), &fileinfo);
|
info.size = file_info.size;
|
||||||
|
info.access_time = file_info.atime;
|
||||||
// Not sure of purpose for below. I hope these don't need to be correct
|
info.modify_time = file_info.mtime;
|
||||||
info.flags |= rIsDir(dir_path) ? DirEntry_TypeDir : DirEntry_TypeFile;
|
info.create_time = file_info.ctime;
|
||||||
if(fileinfo.isWritable) info.flags |= DirEntry_PermWritable;
|
|
||||||
info.flags |= DirEntry_PermReadable; // Always?
|
|
||||||
info.flags |= DirEntry_PermExecutable; // Always?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -410,35 +410,47 @@ namespace vm
|
||||||
static_assert(!sizeof(AT), "vm::_ptr_base<> error: use RT(T...) format for functions instead of RT(*)(T...)");
|
static_assert(!sizeof(AT), "vm::_ptr_base<> error: use RT(T...) format for functions instead of RT(*)(T...)");
|
||||||
};
|
};
|
||||||
|
|
||||||
//BE pointer to LE data
|
// BE pointer to LE data
|
||||||
template<typename T, int lvl = 1, typename AT = u32> using bptrl = _ptr_base<T, lvl, typename to_be_t<AT>::type>;
|
template<typename T, int lvl = 1, typename AT = u32> using bptrl = _ptr_base<T, lvl, typename to_be_t<AT>::type>;
|
||||||
|
|
||||||
//BE pointer to BE data
|
// BE pointer to BE data
|
||||||
template<typename T, int lvl = 1, typename AT = u32> using bptrb = _ptr_base<typename to_be_t<T>::type, lvl, typename to_be_t<AT>::type>;
|
template<typename T, int lvl = 1, typename AT = u32> using bptrb = _ptr_base<typename to_be_t<T>::type, lvl, typename to_be_t<AT>::type>;
|
||||||
|
|
||||||
//LE pointer to BE data
|
// LE pointer to BE data
|
||||||
template<typename T, int lvl = 1, typename AT = u32> using lptrb = _ptr_base<typename to_be_t<T>::type, lvl, AT>;
|
template<typename T, int lvl = 1, typename AT = u32> using lptrb = _ptr_base<typename to_be_t<T>::type, lvl, AT>;
|
||||||
|
|
||||||
//LE pointer to LE data
|
// LE pointer to LE data
|
||||||
template<typename T, int lvl = 1, typename AT = u32> using lptrl = _ptr_base<T, lvl, AT>;
|
template<typename T, int lvl = 1, typename AT = u32> using lptrl = _ptr_base<T, lvl, AT>;
|
||||||
|
|
||||||
namespace ps3
|
namespace ps3
|
||||||
{
|
{
|
||||||
//default pointer for HLE functions (LE pointer to BE data)
|
// default pointer for HLE functions (LE pointer to BE data)
|
||||||
template<typename T, int lvl = 1, typename AT = u32> using ptr = lptrb<T, lvl, AT>;
|
template<typename T, int lvl = 1, typename AT = u32> using ptr = lptrb<T, lvl, AT>;
|
||||||
|
|
||||||
//default pointer for HLE structures (BE pointer to BE data)
|
// default pointer for HLE structures (BE pointer to BE data)
|
||||||
template<typename T, int lvl = 1, typename AT = u32> using bptr = bptrb<T, lvl, AT>;
|
template<typename T, int lvl = 1, typename AT = u32> using bptr = bptrb<T, lvl, AT>;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace psv
|
namespace psv
|
||||||
{
|
{
|
||||||
//default pointer for HLE functions & structures (LE pointer to LE data)
|
// default pointer for HLE functions & structures (LE pointer to LE data)
|
||||||
template<typename T, int lvl = 1, typename AT = u32> using ptr = lptrl<T, lvl, AT>;
|
template<typename T, int lvl = 1, typename AT = u32> using ptr = lptrl<T, lvl, AT>;
|
||||||
}
|
}
|
||||||
|
|
||||||
//PS3 emulation is main now, so lets it be as default
|
// PS3 emulation is main now, so lets it be as default
|
||||||
using namespace ps3;
|
using namespace ps3;
|
||||||
|
|
||||||
|
struct null_t
|
||||||
|
{
|
||||||
|
template<typename T, int lvl, typename AT> operator _ptr_base<T, lvl, AT>() const
|
||||||
|
{
|
||||||
|
const std::array<AT, 1> value = {};
|
||||||
|
return _ptr_base<T, lvl, AT>::make(value[0]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// vm::null is convertible to any vm::ptr type as null pointer in virtual memory
|
||||||
|
static const null_t null;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace fmt
|
namespace fmt
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -271,11 +271,11 @@ struct SaveDataEntry
|
||||||
std::string title;
|
std::string title;
|
||||||
std::string subtitle;
|
std::string subtitle;
|
||||||
std::string details;
|
std::string details;
|
||||||
u32 sizeKB;
|
u64 sizeKB;
|
||||||
s64 st_atime_;
|
s64 atime;
|
||||||
s64 st_mtime_;
|
s64 mtime;
|
||||||
s64 st_ctime_;
|
s64 ctime;
|
||||||
void* iconBuf;
|
//void* iconBuf;
|
||||||
u32 iconBufSize;
|
//u32 iconBufSize;
|
||||||
bool isNew;
|
bool isNew;
|
||||||
};
|
};
|
||||||
|
|
|
@ -72,7 +72,6 @@ Emulator::~Emulator()
|
||||||
delete m_callback_manager;
|
delete m_callback_manager;
|
||||||
delete m_event_manager;
|
delete m_event_manager;
|
||||||
delete m_module_manager;
|
delete m_module_manager;
|
||||||
delete m_sync_prim_manager;
|
|
||||||
delete m_vfs;
|
delete m_vfs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ class CallbackManager;
|
||||||
class CPUThread;
|
class CPUThread;
|
||||||
class EventManager;
|
class EventManager;
|
||||||
class ModuleManager;
|
class ModuleManager;
|
||||||
class SyncPrimManager;
|
|
||||||
struct VFS;
|
struct VFS;
|
||||||
|
|
||||||
struct EmuInfo
|
struct EmuInfo
|
||||||
|
@ -91,7 +90,6 @@ class Emulator
|
||||||
CallbackManager* m_callback_manager;
|
CallbackManager* m_callback_manager;
|
||||||
EventManager* m_event_manager;
|
EventManager* m_event_manager;
|
||||||
ModuleManager* m_module_manager;
|
ModuleManager* m_module_manager;
|
||||||
SyncPrimManager* m_sync_prim_manager;
|
|
||||||
VFS* m_vfs;
|
VFS* m_vfs;
|
||||||
|
|
||||||
EmuInfo m_info;
|
EmuInfo m_info;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue