renderd7/source/FileSystem.cpp

324 lines
10 KiB
C++
Raw Normal View History

2022-08-04 01:13:26 +02:00
#include <renderd7/FileSystem.hpp>
#include <3ds.h>
#include <cstring>
2022-08-04 02:50:37 +02:00
//Debugging
#include <memory>
#include <renderd7/Ovl.hpp>
#include <renderd7/Toast.hpp>
2022-08-04 01:13:26 +02:00
const char* RenderD7::FileSystem::GetPhysfsError()
{
return PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode());
}
std::string RenderD7::FileSystem::Normalize(const std::string& input)
{
std::string out;
bool seenSep = false, isSep = false;
for (size_t i = 0; i < input.size(); ++i)
{
isSep = (input[i] == '/');
if (!isSep || !seenSep)
out += input[i];
seenSep = isSep;
}
return out;
}
void RenderD7::FileSystem::Initialize()
{
RenderD7::FileSystem::savePath = "";
}
int RenderD7::FileSystem::Init(const char* argv)
{
2022-08-04 02:50:37 +02:00
int res = PHYSFS_init(argv);
if (res != 1)
{
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FileSystem::GetPhysfsError()));
}
return res;
2022-08-04 01:13:26 +02:00
}
bool RenderD7::FileSystem::SetSource(const char* source)
{
if (!PHYSFS_isInit())
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FileSystem::GetPhysfsError()));
2022-08-04 01:13:26 +02:00
return false;
std::string searchPath = source;
if (!PHYSFS_mount(searchPath.c_str(), NULL, 1))
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FileSystem::GetPhysfsError()));
2022-08-04 01:13:26 +02:00
return false;
return true;
}
bool RenderD7::FileSystem::SetIdentity(const char* name, bool append)
{
if (!PHYSFS_isInit())
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FileSystem::GetPhysfsError()));
2022-08-04 01:13:26 +02:00
return false;
std::string old = RenderD7::FileSystem::savePath;
RenderD7::FileSystem::savePath = RenderD7::FileSystem::Normalize(RenderD7::FileSystem::GetUserDirectory() + "/save/" + name);
printf("Save Path set to %s\n", savePath.c_str());
if (!old.empty())
PHYSFS_unmount(old.c_str());
int success = PHYSFS_mount(savePath.c_str(), NULL, append);
printf("Save Path mounted %d\n", success);
PHYSFS_setWriteDir(nullptr);
return true;
}
std::string RenderD7::FileSystem::GetSaveDirectory()
{
return RenderD7::FileSystem::Normalize(RenderD7::FileSystem::GetUserDirectory() + "/save");
}
bool RenderD7::FileSystem::SetupWriteDirectory()
{
if (!PHYSFS_isInit())
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FileSystem::GetPhysfsError()));
2022-08-04 01:13:26 +02:00
return false;
if (RenderD7::FileSystem::savePath.empty())
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", "Path is Empty"));
2022-08-04 01:13:26 +02:00
return false;
std::string tmpWritePath = RenderD7::FileSystem::savePath;
std::string tmpDirectoryPath = RenderD7::FileSystem::savePath;
if (RenderD7::FileSystem::savePath.find(RenderD7::FileSystem::GetUserDirectory()) == 0)
{
tmpWritePath = RenderD7::FileSystem::GetUserDirectory();
tmpDirectoryPath = savePath.substr(RenderD7::FileSystem::GetUserDirectory().length());
/* strip leading '/' characters from the path we want to create */
size_t startPosition = tmpDirectoryPath.find_first_not_of('/');
if (startPosition != std::string::npos)
tmpDirectoryPath = tmpDirectoryPath.substr(startPosition);
}
if (!PHYSFS_setWriteDir(tmpWritePath.c_str()))
{
printf("Failed to set write dir to %s\n", tmpWritePath.c_str());
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FormatString("Failed to set write dir to %s\n", tmpWritePath.c_str())));
2022-08-04 01:13:26 +02:00
return false;
}
if (!RenderD7::FileSystem::CreateDirectory(tmpDirectoryPath.c_str()))
{
printf("Failed to create dir %s\n", tmpDirectoryPath.c_str());
/* clear the write directory in case of error */
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FormatString("Failed to create dir %s\n", tmpDirectoryPath.c_str())));
2022-08-04 01:13:26 +02:00
PHYSFS_setWriteDir(nullptr);
return false;
}
if (!PHYSFS_setWriteDir(savePath.c_str()))
{
printf("Failed to set write dir to %s\n", savePath.c_str());
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FormatString("Failed to set write dir to %s\n", savePath.c_str())));
2022-08-04 01:13:26 +02:00
return false;
}
if (!PHYSFS_mount(savePath.c_str(), nullptr, 0))
{
printf("Failed to mount write dir (%s)\n", RenderD7::FileSystem::GetPhysfsError());
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FormatString("Failed to mount write dir (%s)\n", RenderD7::FileSystem::GetPhysfsError())));
2022-08-04 01:13:26 +02:00
/* clear the write directory in case of error */
PHYSFS_setWriteDir(nullptr);
return false;
}
return true;
}
std::string RenderD7::FileSystem::GetUserDirectory()
{
return RenderD7::FileSystem::Normalize(PHYSFS_getPrefDir("npi-d7", "renderd7"));
}
bool RenderD7::FileSystem::GetInfo(const char* filename, RenderD7::FileSystem::Info& info)
{
if (!PHYSFS_isInit())
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FileSystem::GetPhysfsError()));
2022-08-04 01:13:26 +02:00
return false;
PHYSFS_Stat stat = {};
if (!PHYSFS_stat(filename, &stat))
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FileSystem::GetPhysfsError()));
2022-08-04 01:13:26 +02:00
return false;
info.mod_time = std::min<int64_t>(stat.modtime, RenderD7::FileSystem::MAX_STAMP);
info.size = std::min<int64_t>(stat.filesize, RenderD7::FileSystem::MAX_STAMP);
if (stat.filetype == PHYSFS_FILETYPE_REGULAR)
info.type = RenderD7::FileSystem::FileType_File;
else if (stat.filetype == PHYSFS_FILETYPE_DIRECTORY)
info.type = RenderD7::FileSystem::FileType_Directory;
else if (stat.filetype == PHYSFS_FILETYPE_SYMLINK)
info.type = RenderD7::FileSystem::FileType_SymLink;
else
info.type = RenderD7::FileSystem::FileType_Other;
return true;
}
void RenderD7::FileSystem::GetDirectoryItems(const char* path, std::vector<std::string>& items)
{
if (!PHYSFS_isInit())
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FileSystem::GetPhysfsError()));
2022-08-04 01:13:26 +02:00
return;
char** results = PHYSFS_enumerateFiles(path);
if (results == nullptr)
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FileSystem::GetPhysfsError()));
2022-08-04 01:13:26 +02:00
return;
for (char** item = results; *item != 0; item++)
items.push_back(*item);
PHYSFS_freeList(results);
}
bool RenderD7::FileSystem::OpenFile(File& file, const char* name, FileMode mode)
{
if (mode == FileMode_Closed)
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FileSystem::GetPhysfsError()));
2022-08-04 01:13:26 +02:00
return false;
if (!PHYSFS_isInit())
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FileSystem::GetPhysfsError()));
2022-08-04 01:13:26 +02:00
return false;
if (file.handle)
RenderD7::FileSystem::CloseFile(file);
if (mode == FileMode_Read && !PHYSFS_exists(name))
{
printf("Could not open file %s, does not exist.\n", name);
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FormatString("Could not open file %s, does not exist.\n", name)));
2022-08-04 01:13:26 +02:00
return false;
}
if ((mode == FileMode_Write) &&
(PHYSFS_getWriteDir() == nullptr && RenderD7::FileSystem::SetupWriteDirectory()))
{
printf("Could not set write directory.\n");
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FormatString("Could not set write directory.\n")));
2022-08-04 01:13:26 +02:00
return false;
}
PHYSFS_getLastErrorCode();
switch (mode)
{
case FileMode_Read:
file.handle = PHYSFS_openRead(name);
break;
case FileMode_Write:
file.handle = PHYSFS_openWrite(name);
break;
default:
break;
}
if (!file.handle)
{
const char* error = RenderD7::FileSystem::GetPhysfsError();
if (error == nullptr)
error = "unknown error";
printf("Could not open file %s (%s)\n", name, error);
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FormatString("Could not open file %s (%s)\n", name, error)));
2022-08-04 01:13:26 +02:00
return false;
}
file.mode = mode;
return true;
}
bool RenderD7::FileSystem::CloseFile(File& file)
{
if (file.handle == nullptr || !PHYSFS_close(file.handle))
return false;
file.handle = nullptr;
return true;
}
bool RenderD7::FileSystem::CreateDirectory(const char* name)
{
if (!PHYSFS_isInit())
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FileSystem::GetPhysfsError()));
2022-08-04 01:13:26 +02:00
return false;
if (PHYSFS_getWriteDir() == nullptr && !RenderD7::FileSystem::SetupWriteDirectory())
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FileSystem::GetPhysfsError()));
2022-08-04 01:13:26 +02:00
return false;
if (!PHYSFS_mkdir(name))
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FileSystem::GetPhysfsError()));
2022-08-04 01:13:26 +02:00
return false;
return true;
}
int64_t RenderD7::FileSystem::ReadFile(File& file, void* destination, int64_t size)
{
if (!file.handle || file.mode != FileMode_Read)
{
printf("File is not opened for reading.\n");
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", "File is not opened for reading.\n"));
2022-08-04 01:13:26 +02:00
return 0;
}
if (size > file.GetSize())
size = file.GetSize();
else if (size < 0)
{
printf("Invalid read size %lld\n", size);
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FormatString("Invalid read size %lld\n", size)));
2022-08-04 01:13:26 +02:00
return 0;
}
return PHYSFS_readBytes(file.handle, destination, (PHYSFS_uint64)size);
}
bool RenderD7::FileSystem::WriteFile(File& file, const void* data, int64_t size)
{
if (!file.handle || file.mode != FileMode_Write)
{
printf("File is not opened for writing.\n");
2022-08-04 02:50:37 +02:00
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", "File is not opened for writing.\n"));
2022-08-04 01:13:26 +02:00
return false;
}
int64_t written = PHYSFS_writeBytes(file.handle, data, (PHYSFS_uint64)size);
2022-08-04 02:50:37 +02:00
if (written != size){
RenderD7::AddOvl(std::make_unique<RenderD7::Toast>("PHYSFS-Error", RenderD7::FileSystem::GetPhysfsError()));
2022-08-04 01:13:26 +02:00
return false;
2022-08-04 02:50:37 +02:00
}
2022-08-04 01:13:26 +02:00
return true;
}