Skip to content

Commit

Permalink
Wrap the filesystem stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
Dextinfire committed Oct 5, 2024
1 parent f127f68 commit 986a6b8
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 58 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ set(Impacto_Src
src/renderer/3d/animation.cpp
src/renderer/3d/modelanimator.cpp

src/io/filemeta.cpp
src/io/vfs.cpp
src/io/assetpath.cpp
src/io/memorystream.cpp
Expand Down
50 changes: 24 additions & 26 deletions src/games/cclcc/savesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

#include <cstdint>
#include <ctime>
#include <filesystem>
#include <system_error>

namespace Impacto {
Expand All @@ -26,39 +25,38 @@ using namespace Impacto::Profile::ScriptVars;
using namespace Impacto::Profile::Vm;

SaveError SaveSystem::CheckSaveFile() {
std::filesystem::path savePath(SaveFilePath);
std::error_code ec;
if (!std::filesystem::exists(savePath, ec)) {
if (ec) {
ImpLog(LL_Error, LC_IO,
"Failed to check if save file exists, error: \"%s\"\n",
ec.message().c_str());
return SaveFailed;
}
IoError existsState = Io::PathExists(SaveFilePath);
if (existsState == IoError_NotFound) {
return SaveNotFound;
} else if (existsState == IoError_Fail) {
ImpLog(LL_Error, LC_IO,
"Failed to check if save file exists, error: \"%s\"\n",
ec.message().c_str());
return SaveFailed;
}
if (std::filesystem::file_size(savePath, ec) != SaveFileSize) {
if (ec) {
ImpLog(LL_Error, LC_IO, "Failed to get save file size, error: \"%s\"\n",
ec.message().c_str());
return SaveFailed;
}
auto saveFileSize = Io::GetFileSize(SaveFilePath);
if (saveFileSize == IoError_Fail) {
ImpLog(LL_Error, LC_IO, "Failed to get save file size, error: \"%s\"\n",
ec.message().c_str());
return SaveFailed;
} else if (saveFileSize != SaveFileSize) {
return SaveCorrupted;
}
using PermsFlag = std::filesystem::perms;
auto checkPermsBit = [](PermsFlag perms, PermsFlag flag) {
auto checkPermsBit = [](Io::FilePermissionsFlags perms,
Io::FilePermissionsFlags flag) {
return to_underlying(perms) & to_underlying(flag);
};

if (auto perms = std::filesystem::status(savePath, ec).permissions();
(!checkPermsBit(perms, PermsFlag::owner_read) ||
!checkPermsBit(perms, PermsFlag::owner_write))) {
if (ec) {
ImpLog(LL_Error, LC_IO,
"Failed to get save file permissions, error: \"%s\"\n",
ec.message().c_str());
return SaveFailed;
}
Io::FilePermissionsFlags perms;
IoError permsState = Io::GetFilePermissions(SaveFilePath, perms);
if (permsState == IoError_Fail) {
ImpLog(LL_Error, LC_IO,
"Failed to get save file permissions, error: \"%s\"\n",
ec.message().c_str());
return SaveFailed;
} else if ((!checkPermsBit(perms, Io::FilePermissionsFlags::owner_read) ||
!checkPermsBit(perms, Io::FilePermissionsFlags::owner_write))) {
return SaveWrongUser;
}
return SaveOK;
Expand Down
61 changes: 61 additions & 0 deletions src/io/filemeta.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@


#include "filemeta.h"
#include "../log.h"
#include <system_error>

namespace Impacto {
namespace Io {

inline int64_t GetFileSize(std::string const& path) {
std::error_code ec;
uintmax_t result = std::filesystem::file_size(path, ec);
if (ec) {
ImpLog(LL_Error, LC_IO,
"Error getting file size of file \"%s\", error: \"%s\"\n",
path.c_str(), ec.message().c_str());
return IoError_Fail;
}
// Hopefully no one has a file of size between int64_t max and uint64_t max
return static_cast<int64_t>(result);
}

inline IoError PathExists(std::string const& path) {
std::error_code ec;
bool result = std::filesystem::exists(path, ec);
if (ec) {
ImpLog(LL_Error, LC_IO,
"Error checking for file existence for file \"%s\", error: \"%s\"\n",
path.c_str(), ec.message().c_str());
return IoError_Fail;
}
return result == false ? IoError_NotFound : IoError_OK;
}

inline int8_t CreateDirectories(std::string const& path) {
std::error_code ec;
bool result = std::filesystem::create_directories(path, ec);
if (ec) {
ImpLog(LL_Error, LC_IO,
"Error creating directories for file \"%s\", error: \"%s\"\n",
path.c_str(), ec.message().c_str());
return IoError_Fail;
}
return result;
}

inline IoError GetFilePermissions(std::string const& path,
FilePermissionsFlags& flags) {
std::error_code ec;
flags = std::filesystem::status(path, ec).permissions();
if (ec) {
ImpLog(LL_Error, LC_IO,
"Error retrieving permissions for file \"%s\", error: \"%s\"\n",
path.c_str(), ec.message().c_str());
return IoError_Fail;
}
return IoError_OK;
}

} // namespace Io
} // namespace Impacto
11 changes: 10 additions & 1 deletion src/io/filemeta.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

#include <string>
#include <cstdint>

#include <filesystem>
#include "io.h"
namespace Impacto {
namespace Io {

Expand All @@ -14,5 +15,13 @@ struct FileMeta {
int64_t Size = 0;
};

using FilePermissionsFlags = std::filesystem::perms;

int64_t GetFileSize(std::string const& path);
IoError PathExists(std::string const& path);
int8_t CreateDirectories(std::string const& path);
IoError GetFilePermissions(std::string const& path,
FilePermissionsFlags& flags);

} // namespace Io
} // namespace Impacto
40 changes: 16 additions & 24 deletions src/io/physicalfilestream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ namespace Io {
std::ios_base::openmode PhysicalFileStream::PrepareFileOpenMode(
CreateFlags flags, std::error_code& ec) {
std::ios_base::openmode mode = std::ios::binary;
bool fileExists = std::filesystem::exists(SourceFileName, ec);
IoError fileExists = PathExists(SourceFileName);
if (ec) {
ImpLog(LL_Error, LC_IO,
"Failed to check whether file exists \"%s\", error: \"%s\"\n",
SourceFileName.generic_string().c_str(), ec.message().c_str());
SourceFileName.c_str(), ec.message().c_str());
return {};
}

Expand All @@ -24,7 +24,7 @@ std::ios_base::openmode PhysicalFileStream::PrepareFileOpenMode(
if (writeNoExistNoCreate || readNoExist) {
ec = std::make_error_code(std::errc::no_such_file_or_directory);
ImpLog(LL_Error, LC_IO, "Failed to open stream \"%s\", error: \"%s\"\n",
SourceFileName.generic_string().c_str(), ec.message().c_str());
SourceFileName.c_str(), ec.message().c_str());
return {};
}

Expand Down Expand Up @@ -55,11 +55,9 @@ std::ios_base::openmode PhysicalFileStream::PrepareFileOpenMode(
if (flags & APPEND) mode |= std::ios::app;
if (truncFlag) mode |= std::ios::trunc;
if (flags & CREATE_DIRS) {
std::filesystem::create_directories(SourceFileName.parent_path(), ec);
if (ec) {
ImpLog(LL_Error, LC_IO,
"Failed to create directories for file \"%s\", error: \"%s\"\n",
SourceFileName.generic_string().c_str(), ec.message().c_str());
auto result = Io::CreateDirectories(SourceFileName);
if (result == IoError_Fail) {
ErrorCode = std::make_error_code(std::errc::io_error);
return {};
}
}
Expand All @@ -68,7 +66,6 @@ std::ios_base::openmode PhysicalFileStream::PrepareFileOpenMode(

IoError PhysicalFileStream::Create(std::string const& fileName, Stream** out,
CreateFlags flags) {
std::error_code ec;
PhysicalFileStream* result = new PhysicalFileStream(fileName, flags);
if (result->ErrorCode) {
ImpLog(LL_Error, LC_IO, "Failed to open file \"%s\", error: \"%s\"\n",
Expand All @@ -84,10 +81,8 @@ IoError PhysicalFileStream::Create(std::string const& fileName, Stream** out,
delete result;
return IoError_Fail;
}
result->Meta.Size = std::filesystem::file_size(result->SourceFileName, ec);
if (ec) {
ImpLog(LL_Error, LC_IO, "Error getting file size: %s\n",
ec.message().c_str());
result->Meta.Size = GetFileSize(result->SourceFileName);
if (result->Meta.Size == IoError_Fail) {
delete result;
return IoError_Fail;
}
Expand All @@ -106,7 +101,7 @@ int64_t PhysicalFileStream::Read(void* buffer, int64_t sz) {
FileStream.read((char*)buffer, bytesToRead);
if (!FileStream) {
ImpLog(LL_Error, LC_IO, "Read failed for file \"%s\" with error: \"%s\"\n",
SourceFileName.string().c_str(),
SourceFileName.c_str(),
std::generic_category().message(errno).c_str());
FileStream.clear(FileStream.rdstate() & ~std::ios::failbit &
~std::ios::eofbit); // Clear only failbit and eofbit
Expand Down Expand Up @@ -141,7 +136,7 @@ int64_t PhysicalFileStream::Seek(int64_t offset, int origin) {
FileStream.seekg(absPos, std::ios::beg);
if (!FileStream && !FileStream.eof()) {
ImpLog(LL_Error, LC_IO, "Seek failed for file \"%s\" with error: \"%s\"\n",
SourceFileName.string().c_str(),
SourceFileName.c_str(),
std::generic_category().message(errno).c_str());
FileStream.clear(FileStream.rdstate() & ~std::ios::failbit &
~std::ios::eofbit); // Clear only failbit and eofbit
Expand All @@ -156,30 +151,27 @@ IoError PhysicalFileStream::Duplicate(Stream** outStream) {
std::error_code ec;
if (result->ErrorCode) {
ImpLog(LL_Error, LC_IO, "Failed to open file \"%s\", error: \"%s\"\n",
SourceFileName.string().c_str(),
result->ErrorCode.message().c_str());
SourceFileName.c_str(), result->ErrorCode.message().c_str());
delete result;
return result->ErrorCode == std::errc::no_such_file_or_directory
? IoError_NotFound
: IoError_Fail;
}
if (!result->FileStream) {
ImpLog(LL_Error, LC_IO, "Failed to open file \"%s\", error: \"%s\"\n",
SourceFileName.string().c_str(),
SourceFileName.c_str(),
std::generic_category().message(errno).c_str());
delete result;
return IoError_Fail;
}
result->Meta.Size = std::filesystem::file_size(SourceFileName, ec);
if (ec) {
ImpLog(LL_Error, LC_IO, "Error getting file size: %s\n",
ec.message().c_str());
result->Meta.Size = GetFileSize(result->SourceFileName);
if (result->Meta.Size == IoError_Fail) {
delete result;
return IoError_Fail;
}
if (result->Seek(Position, RW_SEEK_SET) < 0) {
ImpLog(LL_Error, LC_IO, "Seek failed for file \"%s\" with error: \"%s\"\n",
SourceFileName.string().c_str(),
SourceFileName.c_str(),
std::generic_category().message(errno).c_str());
delete result;
return IoError_Fail;
Expand All @@ -195,7 +187,7 @@ int64_t PhysicalFileStream::Write(void* buffer, int64_t sz, int cnt) {
FileStream.write((char*)buffer, sz * cnt);
if (!FileStream) {
ImpLog(LL_Error, LC_IO, "Write failed for file \"%s\" with error: \"%s\"\n",
SourceFileName.string().c_str(),
SourceFileName.c_str(),
std::generic_category().message(errno).c_str());
FileStream.clear(FileStream.rdstate() & ~std::ios::failbit &
~std::ios::eofbit); // Clear only failbit and eofbit
Expand Down
12 changes: 5 additions & 7 deletions src/io/physicalfilestream.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

#include "stream.h"
#include <fstream>
#include <filesystem>
#include <system_error>
#include "buffering.h"

namespace Impacto {
namespace Io {
Expand All @@ -31,26 +29,26 @@ class PhysicalFileStream : public Stream {
std::ios_base::openmode PrepareFileOpenMode(CreateFlags flags,
std::error_code& ec);

PhysicalFileStream(std::filesystem::path filePath, CreateFlags flags)
PhysicalFileStream(std::string filePath, CreateFlags flags)
: Flags(flags),
SourceFileName(std::move(filePath)),
FileStream(SourceFileName, PrepareFileOpenMode(flags, ErrorCode)) {
Meta.FileName = SourceFileName.string();
Meta.FileName = SourceFileName;
}

PhysicalFileStream(std::filesystem::path filePath)
PhysicalFileStream(std::string filePath)
: PhysicalFileStream(std::move(filePath), CreateFlagsMode::READ) {}

PhysicalFileStream(PhysicalFileStream const& other)
: Flags(other.Flags),
SourceFileName(other.SourceFileName),
FileStream(other.SourceFileName,
PrepareFileOpenMode(Flags, ErrorCode)) {
Meta.FileName = SourceFileName.string();
Meta.FileName = SourceFileName;
}
std::error_code ErrorCode;
CreateFlags Flags;
std::filesystem::path SourceFileName;
std::string SourceFileName;
std::fstream FileStream;
};

Expand Down

0 comments on commit 986a6b8

Please sign in to comment.