vfsLocalDir, rFile routines improved

This commit is contained in:
Nekotekina 2015-04-15 17:27:37 +03:00
parent 2798827066
commit d032bc5691
9 changed files with 334 additions and 667 deletions

View file

@ -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

View file

@ -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);

View file

@ -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)

View file

@ -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;

View file

@ -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

View file

@ -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;
}; };

View file

@ -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;
} }

View file

@ -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;