diff --git a/Source/Core/Common/Src/FileUtil.cpp b/Source/Core/Common/Src/FileUtil.cpp index 8e1bec2809..d6ab33962a 100644 --- a/Source/Core/Common/Src/FileUtil.cpp +++ b/Source/Core/Common/Src/FileUtil.cpp @@ -42,6 +42,7 @@ #endif #include +#include #include #ifndef S_ISDIR @@ -774,6 +775,24 @@ IOFile::~IOFile() Close(); } +IOFile::IOFile(IOFile&& other) + : m_file(NULL), m_good(true) +{ + Swap(other); +} + +IOFile& IOFile::operator=(IOFile other) +{ + Swap(other); + return *this; +} + +void IOFile::Swap(IOFile& other) +{ + std::swap(m_file, other.m_file); + std::swap(m_good, other.m_good); +} + bool IOFile::Open(const std::string& filename, const char openmode[]) { Close(); diff --git a/Source/Core/Common/Src/FileUtil.h b/Source/Core/Common/Src/FileUtil.h index 451b1b6929..2c8bf8f64b 100644 --- a/Source/Core/Common/Src/FileUtil.h +++ b/Source/Core/Common/Src/FileUtil.h @@ -150,7 +150,7 @@ bool ReadFileToString(bool text_file, const char *filename, std::string &str); // simple wrapper for cstdlib file functions to // hopefully will make error checking easier // and make forgetting an fclose() harder -class IOFile : NonCopyable +class IOFile { public: IOFile(); @@ -158,6 +158,11 @@ public: IOFile(const std::string& filename, const char openmode[]); ~IOFile(); + + IOFile(IOFile&& other); + IOFile& operator=(IOFile other); + + void Swap(IOFile& other); bool Open(const std::string& filename, const char openmode[]); bool Close(); @@ -212,6 +217,7 @@ public: void Clear() { m_good = true; std::clearerr(m_file); } private: + IOFile(const IOFile&) /*= delete*/; IOFile& operator=(const IOFile&) /*= delete*/; std::FILE* m_file; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp index 2061a106e0..d65a009a2a 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp @@ -28,17 +28,16 @@ static Common::replace_v replacements; -// This is used by several of the FileIO and /dev/fs functions -std::string HLE_IPC_BuildFilename(const char* _pFilename, int _size) +// This is used by several of the FileIO and /dev/fs functions +std::string HLE_IPC_BuildFilename(std::string path_wii, int _size) { std::string path_full = File::GetUserPath(D_WIIROOT_IDX); - std::string path_wii(_pFilename); if ((path_wii.length() > 0) && (path_wii[1] == '0')) path_full += std::string("/title"); // this looks and feel like a hack... // Replaces chars that FAT32 can't support with strings defined in /sys/replace - for (Common::replace_v::const_iterator i = replacements.begin(); i != replacements.end(); ++i) + for (auto i = replacements.begin(); i != replacements.end(); ++i) { for (size_t j = 0; (j = path_wii.find(i->first, j)) != path_wii.npos; ++j) path_wii.replace(j, 1, i->second); @@ -82,9 +81,8 @@ void HLE_IPC_CreateVirtualFATFilesystem() } } -CWII_IPC_HLE_Device_FileIO::CWII_IPC_HLE_Device_FileIO(u32 _DeviceID, const std::string& _rDeviceName) +CWII_IPC_HLE_Device_FileIO::CWII_IPC_HLE_Device_FileIO(u32 _DeviceID, const std::string& _rDeviceName) : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName, false) // not a real hardware - , m_pFileHandle(NULL) , m_Mode(0) , m_SeekPos(0) { @@ -108,12 +106,9 @@ bool CWII_IPC_HLE_Device_FileIO::Close(u32 _CommandAddress, bool _bForce) } bool CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode) -{ +{ m_Mode = _Mode; u32 ReturnValue = 0; - - // close the file handle if we get a reopen - //m_pFileHandle.Close(); static const char* const Modes[] = { @@ -122,20 +117,18 @@ bool CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode) "Write only", "Read and Write" }; - - m_Filename = std::string(HLE_IPC_BuildFilename(m_Name.c_str(), 64)); - // The file must exist before we can open it // It should be created by ISFS_CreateFile, not here - if (File::Exists(m_Filename)) + auto const filename = HLE_IPC_BuildFilename(m_Name, 64); + if (File::Exists(filename)) { INFO_LOG(WII_IPC_FILEIO, "FileIO: Open %s (%s == %08X)", m_Name.c_str(), Modes[_Mode], _Mode); ReturnValue = m_DeviceID; } else { - WARN_LOG(WII_IPC_FILEIO, "FileIO: Open (%s) failed - File doesn't exist %s", Modes[_Mode], m_Filename.c_str()); + WARN_LOG(WII_IPC_FILEIO, "FileIO: Open (%s) failed - File doesn't exist %s", Modes[_Mode], filename.c_str()); ReturnValue = FS_FILE_NOT_EXIST; } @@ -145,55 +138,43 @@ bool CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode) return true; } - - -bool CWII_IPC_HLE_Device_FileIO::OpenFile() +File::IOFile CWII_IPC_HLE_Device_FileIO::OpenFile() { + const char* open_mode = ""; + switch (m_Mode) { case ISFS_OPEN_READ: - { - m_pFileHandle.Open(m_Filename, "rb"); + open_mode = "rb"; break; - } + case ISFS_OPEN_WRITE: - { - m_pFileHandle.Open(m_Filename, "r+b"); - break; - } case ISFS_OPEN_RW: - { - m_pFileHandle.Open(m_Filename, "r+b"); + open_mode = "r+b"; break; - } + default: - { PanicAlertT("FileIO: Unknown open mode : 0x%02x", m_Mode); break; } - } - return m_pFileHandle.IsOpen(); + + return File::IOFile(HLE_IPC_BuildFilename(m_Name, 64), open_mode); } -void CWII_IPC_HLE_Device_FileIO::CloseFile() -{ - m_pFileHandle.Close(); -} - -bool CWII_IPC_HLE_Device_FileIO::Seek(u32 _CommandAddress) +bool CWII_IPC_HLE_Device_FileIO::Seek(u32 _CommandAddress) { u32 ReturnValue = FS_RESULT_FATAL; const u32 SeekPosition = Memory::Read_U32(_CommandAddress + 0xC); const u32 Mode = Memory::Read_U32(_CommandAddress + 0x10); - - if (OpenFile()) + if (auto file = OpenFile()) { ReturnValue = FS_RESULT_FATAL; - const u64 fileSize = m_pFileHandle.GetSize(); + const u64 fileSize = file.GetSize(); INFO_LOG(WII_IPC_FILEIO, "FileIO: Seek Pos: 0x%08x, Mode: %i (%s, Length=0x%08llx)", SeekPosition, Mode, m_Name.c_str(), fileSize); - switch (Mode){ + switch (Mode) + { case 0: { if (SeekPosition <= fileSize) @@ -230,7 +211,6 @@ bool CWII_IPC_HLE_Device_FileIO::Seek(u32 _CommandAddress) break; } } - CloseFile(); } else { @@ -248,18 +228,18 @@ bool CWII_IPC_HLE_Device_FileIO::Read(u32 _CommandAddress) const u32 Size = Memory::Read_U32(_CommandAddress + 0x10); - if (OpenFile()) + if (auto file = OpenFile()) { - if (m_Mode == ISFS_OPEN_WRITE) + if (m_Mode == ISFS_OPEN_WRITE) { WARN_LOG(WII_IPC_FILEIO, "FileIO: Attempted to read 0x%x bytes to 0x%08x on write-only file %s", Size, Address, m_Name.c_str()); } - else + else { INFO_LOG(WII_IPC_FILEIO, "FileIO: Read 0x%x bytes to 0x%08x from %s", Size, Address, m_Name.c_str()); - m_pFileHandle.Seek(m_SeekPos, SEEK_SET); - ReturnValue = (u32)fread(Memory::GetPointer(Address), 1, Size, m_pFileHandle.GetHandle()); - if (ReturnValue != Size && ferror(m_pFileHandle.GetHandle())) + file.Seek(m_SeekPos, SEEK_SET); + ReturnValue = (u32)fread(Memory::GetPointer(Address), 1, Size, file.GetHandle()); + if (ReturnValue != Size && ferror(file.GetHandle())) { ReturnValue = FS_EACCESS; } @@ -269,7 +249,6 @@ bool CWII_IPC_HLE_Device_FileIO::Read(u32 _CommandAddress) } } - CloseFile(); } else { @@ -288,23 +267,22 @@ bool CWII_IPC_HLE_Device_FileIO::Write(u32 _CommandAddress) const u32 Size = Memory::Read_U32(_CommandAddress + 0x10); - if (OpenFile()) + if (auto file = OpenFile()) { - if (m_Mode == ISFS_OPEN_READ) + if (m_Mode == ISFS_OPEN_READ) { WARN_LOG(WII_IPC_FILEIO, "FileIO: Attempted to write 0x%x bytes from 0x%08x to read-only file %s", Size, Address, m_Name.c_str()); } else { INFO_LOG(WII_IPC_FILEIO, "FileIO: Write 0x%04x bytes from 0x%08x to %s", Size, Address, m_Name.c_str()); - m_pFileHandle.Seek(m_SeekPos, SEEK_SET); - if (m_pFileHandle.WriteBytes(Memory::GetPointer(Address), Size)) + file.Seek(m_SeekPos, SEEK_SET); + if (file.WriteBytes(Memory::GetPointer(Address), Size)) { ReturnValue = Size; m_SeekPos += Size; } } - CloseFile(); } else { @@ -329,9 +307,9 @@ bool CWII_IPC_HLE_Device_FileIO::IOCtl(u32 _CommandAddress) { case ISFS_IOCTL_GETFILESTATS: { - if (OpenFile()) + if (auto file = OpenFile()) { - u32 m_FileLength = (u32)m_pFileHandle.GetSize(); + u32 m_FileLength = (u32)file.GetSize(); const u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18); INFO_LOG(WII_IPC_FILEIO, "FileIO: ISFS_IOCTL_GETFILESTATS"); @@ -339,7 +317,6 @@ bool CWII_IPC_HLE_Device_FileIO::IOCtl(u32 _CommandAddress) Memory::Write_U32(m_FileLength, BufferOut); Memory::Write_U32(m_SeekPos, BufferOut+4); - CloseFile(); } else { @@ -365,30 +342,6 @@ void CWII_IPC_HLE_Device_FileIO::DoState(PointerWrap &p) { DoStateShared(p); - bool have_file_handle = (m_pFileHandle != 0); - s32 seek = (have_file_handle) ? (s32)m_pFileHandle.Tell() : 0; - - p.Do(have_file_handle); p.Do(m_Mode); - p.Do(seek); p.Do(m_SeekPos); - p.Do(m_Filename); - - if (p.GetMode() == PointerWrap::MODE_READ) - { - int mode = m_Mode; - bool active = m_Active; - if (have_file_handle) - { - Open(0, m_Mode); - _dbg_assert_msg_(WII_IPC_HLE, m_pFileHandle, "bad filehandle"); - } - else - Close(0, true); - m_Mode = mode; - m_Active = active; - } - - if (have_file_handle) - m_pFileHandle.Seek(seek, SEEK_SET); } diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.h index ff34a43a20..1ac839e70d 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.h @@ -21,7 +21,7 @@ #include "WII_IPC_HLE_Device.h" #include "FileUtil.h" -std::string HLE_IPC_BuildFilename(const char* _pFilename, int _size); +std::string HLE_IPC_BuildFilename(std::string _pFilename, int _size); void HLE_IPC_CreateVirtualFATFilesystem(); class CWII_IPC_HLE_Device_FileIO : public IWII_IPC_HLE_Device @@ -39,8 +39,7 @@ public: bool IOCtl(u32 _CommandAddress); void DoState(PointerWrap &p); - bool OpenFile(); - void CloseFile(); + File::IOFile OpenFile(); private: enum @@ -76,12 +75,8 @@ private: ISFS_IOCTL_SHUTDOWN }; - File::IOFile m_pFileHandle; u32 m_Mode; - u32 m_SeekPos; - - std::string m_Filename; }; #endif diff --git a/Source/Core/Core/Src/State.cpp b/Source/Core/Core/Src/State.cpp index 200642eccb..084a94e5f6 100644 --- a/Source/Core/Core/Src/State.cpp +++ b/Source/Core/Core/Src/State.cpp @@ -71,7 +71,7 @@ static Common::Event g_compressAndDumpStateSyncEvent; static std::thread g_save_thread; // Don't forget to increase this after doing changes on the savestate system -static const u32 STATE_VERSION = 12; +static const u32 STATE_VERSION = 13; struct StateHeader {