Merge pull request #275 from wheremyfoodat/SystemSaveData

Moar filesystem
This commit is contained in:
wheremyfoodat 2023-09-14 23:13:19 +03:00 committed by GitHub
commit fa6a257b43
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 136 additions and 9 deletions

View file

@ -6,7 +6,7 @@ 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;
}
@ -14,14 +14,10 @@ class SystemSaveDataArchive : public ArchiveBase {
//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;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -7,6 +7,7 @@ namespace BOSSCommands {
UnregisterStorage = 0x00030000,
GetTaskStorageInfo = 0x00040000,
RegisterNewArrivalEvent = 0x00080002,
SetOptoutFlag = 0x00090040,
GetOptoutFlag = 0x000A0000,
RegisterTask = 0x000B00C2,
UnregisterTask = 0x000C0082,
@ -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;
@ -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));

View file

@ -16,6 +16,8 @@ namespace FSCommands {
OpenFile = 0x080201C2,
OpenFileDirectly = 0x08030204,
DeleteFile = 0x08040142,
DeleteDirectory = 0x08060142,
DeleteDirectoryRecursively = 0x08070142,
CreateFile = 0x08080202,
CreateDirectory = 0x08090182,
OpenDirectory = 0x080B0102,
@ -26,6 +28,7 @@ namespace FSCommands {
GetFreeBytes = 0x08120080,
IsSdmcDetected = 0x08170000,
IsSdmcWritable = 0x08180000,
CardSlotIsInserted = 0x08210000,
AbnegateAccessRight = 0x08400040,
GetFormatInfo = 0x084500C2,
GetArchiveResource = 0x08490040,
@ -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;
@ -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);
@ -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);
}

View file

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