Skip to content

Commit

Permalink
Merge pull request #275 from wheremyfoodat/SystemSaveData
Browse files Browse the repository at this point in the history
Moar filesystem
  • Loading branch information
wheremyfoodat authored Sep 14, 2023
2 parents a7a4b81 + 103cb6a commit fa6a257
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 9 deletions.
10 changes: 3 additions & 7 deletions include/fs/archive_system_save_data.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,18 @@ class SystemSaveDataArchive : public ArchiveBase {
SystemSaveDataArchive(Memory& mem) : ArchiveBase(mem) {}

u64 getFreeBytes() override {
Helpers::panic("Unimplemented GetFreeBytes for SystemSaveData archive");
Helpers::warn("Unimplemented GetFreeBytes for SystemSaveData archive");
return 32_MB;
}

std::string name() override { return "SystemSaveData"; }

//HorizonResult createDirectory(const FSPath& path) override;
HorizonResult createFile(const FSPath& path, u64 size) override;

HorizonResult deleteFile(const FSPath& path) override {
Helpers::panic("Unimplemented DeleteFile for SystemSaveData archive");
return Result::Success;
};
HorizonResult deleteFile(const FSPath& path) override;

Rust::Result<ArchiveBase*, HorizonResult> openArchive(const FSPath& path) override;
//Rust::Result<DirectorySession, HorizonResult> openDirectory(const FSPath& path) override;
Rust::Result<DirectorySession, HorizonResult> openDirectory(const FSPath& path) override;

FileDescriptor openFile(const FSPath& path, const FilePerms& perms) override;

Expand Down
1 change: 1 addition & 0 deletions include/services/boss.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class BOSSService {
void registerStorageEntry(u32 messagePointer);
void registerTask(u32 messagePointer);
void sendProperty(u32 messagePointer);
void setOptoutFlag(u32 messagePointer);
void startTask(u32 messagePointer);
void unregisterStorage(u32 messagePointer);
void unregisterTask(u32 messagePointer);
Expand Down
2 changes: 2 additions & 0 deletions include/services/fs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,13 @@ class FSService {

// Service commands
void abnegateAccessRight(u32 messagePointer);
void cardSlotIsInserted(u32 messagePointer);
void createDirectory(u32 messagePointer);
void createExtSaveData(u32 messagePointer);
void createFile(u32 messagePointer);
void closeArchive(u32 messagePointer);
void controlArchive(u32 messagePointer);
void deleteDirectory(u32 messagePointer);
void deleteExtSaveData(u32 messagePointer);
void deleteFile(u32 messagePointer);
void formatSaveData(u32 messagePointer);
Expand Down
3 changes: 2 additions & 1 deletion src/core/fs/archive_save_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ HorizonResult SaveDataArchive::createDirectory(const FSPath& path) {

HorizonResult SaveDataArchive::deleteFile(const FSPath& path) {
if (path.type == PathType::UTF16) {
if (!isPathSafe<PathType::UTF16>(path))
if (!isPathSafe<PathType::UTF16>(path)) {
Helpers::panic("Unsafe path in SaveData::DeleteFile");
}

fs::path p = IOFile::getAppData() / "SaveData";
p += fs::path(path.utf16_string).make_preferred();
Expand Down
32 changes: 31 additions & 1 deletion src/core/fs/archive_sdmc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,37 @@
namespace fs = std::filesystem;

HorizonResult SDMCArchive::createFile(const FSPath& path, u64 size) {
Helpers::panic("[SDMC] CreateFile not yet supported");
if (path.type == PathType::UTF16) {
if (!isPathSafe<PathType::UTF16>(path)) {
Helpers::panic("Unsafe path in SDMC::CreateFile");
}

fs::path p = IOFile::getAppData() / "SDMC";
p += fs::path(path.utf16_string).make_preferred();

if (fs::exists(p)) {
return Result::FS::AlreadyExists;
}

IOFile file(p.string().c_str(), "wb");

// If the size is 0, leave the file empty and return success
if (size == 0) {
file.close();
return Result::Success;
}

// If it is not empty, seek to size - 1 and write a 0 to create a file of size "size"
else if (file.seek(size - 1, SEEK_SET) && file.writeBytes("", 1).second == 1) {
file.close();
return Result::Success;
}

file.close();
return Result::FS::FileTooLarge;
}

Helpers::panic("SDMC::CreateFile: Failed");
return Result::Success;
}

Expand Down
59 changes: 59 additions & 0 deletions src/core/fs/archive_system_save_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,63 @@ HorizonResult SystemSaveDataArchive::createFile(const FSPath& path, u64 size) {

Helpers::panic("SystemSaveData::CreateFile: Failed");
return Result::Success;
}


HorizonResult SystemSaveDataArchive::deleteFile(const FSPath& path) {
if (path.type == PathType::UTF16) {
if (!isPathSafe<PathType::UTF16>(path)) {
Helpers::panic("Unsafe path in SystemSaveData::DeleteFile");
}

fs::path p = IOFile::getAppData() / ".." / "SharedFiles" / "SystemSaveData";
p += fs::path(path.utf16_string).make_preferred();

if (fs::is_directory(p)) {
Helpers::panic("SystemSaveData::DeleteFile: Tried to delete directory");
}

if (!fs::is_regular_file(p)) {
return Result::FS::FileNotFoundAlt;
}

std::error_code ec;
bool success = fs::remove(p, ec);

// It might still be possible for fs::remove to fail, if there's eg an open handle to a file being deleted
// In this case, print a warning, but still return success for now
if (!success) {
Helpers::warn("SystemSaveData::DeleteFile: fs::remove failed\n");
}

return Result::Success;
}

Helpers::panic("SystemSaveData::DeleteFile: Unknown path type");
return Result::Success;
}

Rust::Result<DirectorySession, HorizonResult> SystemSaveDataArchive::openDirectory(const FSPath& path) {
if (path.type == PathType::UTF16) {
if (!isPathSafe<PathType::UTF16>(path)) {
Helpers::panic("Unsafe path in SystemSaveData::OpenDirectory");
}

fs::path p = IOFile::getAppData() / ".." / "SharedFiles" / "SystemSaveData";
p += fs::path(path.utf16_string).make_preferred();

if (fs::is_regular_file(p)) {
printf("SystemSaveData: OpenDirectory used with a file path");
return Err(Result::FS::UnexpectedFileOrDir);
}

if (fs::is_directory(p)) {
return Ok(DirectorySession(this, p));
} else {
return Err(Result::FS::FileNotFoundAlt);
}
}

Helpers::panic("SystemSaveData::OpenDirectory: Unimplemented path type");
return Err(Result::Success);
}
11 changes: 11 additions & 0 deletions src/core/services/boss.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace BOSSCommands {
UnregisterStorage = 0x00030000,
GetTaskStorageInfo = 0x00040000,
RegisterNewArrivalEvent = 0x00080002,
SetOptoutFlag = 0x00090040,
GetOptoutFlag = 0x000A0000,
RegisterTask = 0x000B00C2,
UnregisterTask = 0x000C0082,
Expand Down Expand Up @@ -53,6 +54,7 @@ void BOSSService::handleSyncRequest(u32 messagePointer) {
case BOSSCommands::RegisterStorageEntry: registerStorageEntry(messagePointer); break;
case BOSSCommands::RegisterTask: registerTask(messagePointer); break;
case BOSSCommands::SendProperty: sendProperty(messagePointer); break;
case BOSSCommands::SetOptoutFlag: setOptoutFlag(messagePointer); break;
case BOSSCommands::StartTask: startTask(messagePointer); break;
case BOSSCommands::UnregisterStorage: unregisterStorage(messagePointer); break;
case BOSSCommands::UnregisterTask: unregisterTask(messagePointer); break;
Expand All @@ -66,6 +68,15 @@ void BOSSService::initializeSession(u32 messagePointer) {
mem.write32(messagePointer + 4, Result::Success);
}

void BOSSService::setOptoutFlag(u32 messagePointer) {
const s8 flag = static_cast<s8>(mem.read8(messagePointer + 4));
log("BOSS::SetOptoutFlag (flag = %d)\n", flag);
optoutFlag = flag;

mem.write32(messagePointer, IPC::responseHeader(0x9, 1, 0));
mem.write32(messagePointer + 4, Result::Success);
}

void BOSSService::getOptoutFlag(u32 messagePointer) {
log("BOSS::GetOptoutFlag\n");
mem.write32(messagePointer, IPC::responseHeader(0xA, 2, 0));
Expand Down
26 changes: 26 additions & 0 deletions src/core/services/fs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ namespace FSCommands {
OpenFile = 0x080201C2,
OpenFileDirectly = 0x08030204,
DeleteFile = 0x08040142,
DeleteDirectory = 0x08060142,
DeleteDirectoryRecursively = 0x08070142,
CreateFile = 0x08080202,
CreateDirectory = 0x08090182,
OpenDirectory = 0x080B0102,
Expand All @@ -26,6 +28,7 @@ namespace FSCommands {
GetFreeBytes = 0x08120080,
IsSdmcDetected = 0x08170000,
IsSdmcWritable = 0x08180000,
CardSlotIsInserted = 0x08210000,
AbnegateAccessRight = 0x08400040,
GetFormatInfo = 0x084500C2,
GetArchiveResource = 0x08490040,
Expand Down Expand Up @@ -160,11 +163,13 @@ FSPath FSService::readPath(u32 type, u32 pointer, u32 size) {
void FSService::handleSyncRequest(u32 messagePointer) {
const u32 command = mem.read32(messagePointer);
switch (command) {
case FSCommands::CardSlotIsInserted: cardSlotIsInserted(messagePointer); break;
case FSCommands::CreateDirectory: createDirectory(messagePointer); break;
case FSCommands::CreateExtSaveData: createExtSaveData(messagePointer); break;
case FSCommands::CreateFile: createFile(messagePointer); break;
case FSCommands::ControlArchive: controlArchive(messagePointer); break;
case FSCommands::CloseArchive: closeArchive(messagePointer); break;
case FSCommands::DeleteDirectory: deleteDirectory(messagePointer); break;
case FSCommands::DeleteExtSaveData: deleteExtSaveData(messagePointer); break;
case FSCommands::DeleteFile: deleteFile(messagePointer); break;
case FSCommands::FormatSaveData: formatSaveData(messagePointer); break;
Expand Down Expand Up @@ -414,6 +419,18 @@ void FSService::deleteFile(u32 messagePointer) {
mem.write32(messagePointer + 4, static_cast<u32>(res));
}

void FSService::deleteDirectory(u32 messagePointer) {
const Handle archiveHandle = Handle(mem.read64(messagePointer + 8));
const u32 filePathType = mem.read32(messagePointer + 16);
const u32 filePathSize = mem.read32(messagePointer + 20);
const u32 filePathPointer = mem.read32(messagePointer + 28);
log("FS::DeleteDirectory\n");

Helpers::warn("Stubbed FS::DeleteDirectory call!");
mem.write32(messagePointer, IPC::responseHeader(0x806, 1, 0));
mem.write32(messagePointer + 4, Result::Success);
}

void FSService::getFormatInfo(u32 messagePointer) {
const u32 archiveID = mem.read32(messagePointer + 4);
const u32 pathType = mem.read32(messagePointer + 8);
Expand Down Expand Up @@ -690,4 +707,13 @@ void FSService::isSdmcWritable(u32 messagePointer) {
mem.write32(messagePointer, IPC::responseHeader(0x818, 2, 0));
mem.write32(messagePointer + 4, Result::Success);
mem.write8(messagePointer + 8, writeProtected ? 0 : 1);
}

void FSService::cardSlotIsInserted(u32 messagePointer) {
log("FS::CardSlotIsInserted\n");
constexpr bool cardInserted = false;

mem.write32(messagePointer, IPC::responseHeader(0x821, 2, 0));
mem.write32(messagePointer + 4, Result::Success);
mem.write8(messagePointer + 8, cardInserted ? 1 : 0);
}
1 change: 1 addition & 0 deletions src/core/services/service_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ void ServiceManager::registerClient(u32 messagePointer) {
// clang-format off
static std::map<std::string, Handle> serviceMap = {
{ "ac:u", KernelHandles::AC },
{ "act:a", KernelHandles::ACT },
{ "act:u", KernelHandles::ACT },
{ "am:app", KernelHandles::AM },
{ "APT:S", KernelHandles::APT }, // TODO: APT:A, APT:S and APT:U are slightly different
Expand Down

0 comments on commit fa6a257

Please sign in to comment.