From 0eefe6e4d15cbc7a5902dfbe5e7742ef4ea71902 Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 4 Mar 2018 13:03:58 -0500 Subject: [PATCH 1/3] FS: Make EnsureSaveData create the savedata folder when called for the first time. --- src/core/file_sys/filesystem.h | 3 +- src/core/file_sys/romfs_factory.cpp | 2 +- src/core/file_sys/romfs_factory.h | 2 +- src/core/file_sys/savedata_factory.cpp | 34 +++++++++++++------ src/core/file_sys/savedata_factory.h | 4 ++- src/core/hle/service/am/am.cpp | 22 ++++++++++-- .../hle/service/filesystem/filesystem.cpp | 13 +++++++ src/core/hle/service/filesystem/filesystem.h | 7 ++++ 8 files changed, 70 insertions(+), 17 deletions(-) diff --git a/src/core/file_sys/filesystem.h b/src/core/file_sys/filesystem.h index df4e66a0b0..94ad2abf29 100644 --- a/src/core/file_sys/filesystem.h +++ b/src/core/file_sys/filesystem.h @@ -183,10 +183,9 @@ public: /** * Deletes the archive contents and then re-creates the base folder * @param path Path to the archive - * @param format_info Format information for the new archive * @return ResultCode of the operation, 0 on success */ - virtual ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) = 0; + virtual ResultCode Format(const Path& path) = 0; /** * Retrieves the format info about the archive with the specified path diff --git a/src/core/file_sys/romfs_factory.cpp b/src/core/file_sys/romfs_factory.cpp index e0de49f050..b214279489 100644 --- a/src/core/file_sys/romfs_factory.cpp +++ b/src/core/file_sys/romfs_factory.cpp @@ -23,7 +23,7 @@ ResultVal> RomFS_Factory::Open(const Path& pa return MakeResult>(std::move(archive)); } -ResultCode RomFS_Factory::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { +ResultCode RomFS_Factory::Format(const Path& path) { LOG_ERROR(Service_FS, "Unimplemented Format archive %s", GetName().c_str()); // TODO(bunnei): Find the right error code for this return ResultCode(-1); diff --git a/src/core/file_sys/romfs_factory.h b/src/core/file_sys/romfs_factory.h index 10ea139667..e0698e6429 100644 --- a/src/core/file_sys/romfs_factory.h +++ b/src/core/file_sys/romfs_factory.h @@ -23,7 +23,7 @@ public: return "ArchiveFactory_RomFS"; } ResultVal> Open(const Path& path) override; - ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; + ResultCode Format(const Path& path) override; ResultVal GetFormatInfo(const Path& path) const override; private: diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp index 4d83e100fe..c3329ce528 100644 --- a/src/core/file_sys/savedata_factory.cpp +++ b/src/core/file_sys/savedata_factory.cpp @@ -17,20 +17,26 @@ SaveData_Factory::SaveData_Factory(std::string nand_directory) : nand_directory(std::move(nand_directory)) {} ResultVal> SaveData_Factory::Open(const Path& path) { - u64 title_id = Kernel::g_current_process->program_id; - // TODO(Subv): Somehow obtain this value. - u32 user = 0; - std::string save_directory = Common::StringFromFormat("%ssave/%016" PRIX64 "/%08X", - nand_directory.c_str(), title_id, user); + std::string save_directory = GetFullPath(); + // Return an error if the save data doesn't actually exist. + if (!FileUtil::IsDirectory(save_directory)) { + // TODO(Subv): Find out correct error code. + return ResultCode(-1); + } + auto archive = std::make_unique(save_directory); return MakeResult>(std::move(archive)); } -ResultCode SaveData_Factory::Format(const Path& path, - const FileSys::ArchiveFormatInfo& format_info) { - LOG_ERROR(Service_FS, "Unimplemented Format archive %s", GetName().c_str()); - // TODO(bunnei): Find the right error code for this - return ResultCode(-1); +ResultCode SaveData_Factory::Format(const Path& path) { + LOG_WARNING(Service_FS, "Format archive %s", GetName().c_str()); + // Create the save data directory. + if (!FileUtil::CreateFullPath(GetFullPath())) { + // TODO(Subv): Find the correct error code. + return ResultCode(-1); + } + + return RESULT_SUCCESS; } ResultVal SaveData_Factory::GetFormatInfo(const Path& path) const { @@ -39,4 +45,12 @@ ResultVal SaveData_Factory::GetFormatInfo(const Path& path) c return ResultCode(-1); } +std::string SaveData_Factory::GetFullPath() const { + u64 title_id = Kernel::g_current_process->program_id; + // TODO(Subv): Somehow obtain this value. + u32 user = 0; + return Common::StringFromFormat("%ssave/%016" PRIX64 "/%08X/", nand_directory.c_str(), title_id, + user); +} + } // namespace FileSys diff --git a/src/core/file_sys/savedata_factory.h b/src/core/file_sys/savedata_factory.h index 726743fde0..73a42aab6e 100644 --- a/src/core/file_sys/savedata_factory.h +++ b/src/core/file_sys/savedata_factory.h @@ -21,11 +21,13 @@ public: return "SaveData_Factory"; } ResultVal> Open(const Path& path) override; - ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; + ResultCode Format(const Path& path) override; ResultVal GetFormatInfo(const Path& path) const override; private: std::string nand_directory; + + std::string GetFullPath() const; }; } // namespace FileSys diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index d3a674cf63..d9f003ed47 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -2,12 +2,15 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include +#include "core/file_sys/filesystem.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/event.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applet_ae.h" #include "core/hle/service/am/applet_oe.h" #include "core/hle/service/apm/apm.h" +#include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/nvflinger/nvflinger.h" namespace Service { @@ -416,9 +419,24 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) { } void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service, "(STUBBED) called"); + IPC::RequestParser rp{ctx}; + u128 uid = rp.PopRaw(); + + LOG_WARNING(Service, "(STUBBED) called uid = %016" PRIX64 "%016" PRIX64, uid[1], uid[0]); + IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(RESULT_SUCCESS); + + FileSys::Path unused; + auto savedata = FileSystem::OpenFileSystem(FileSystem::Type::SaveData, unused); + if (savedata.Failed()) { + // Create the save data and return an error indicating that the operation was performed. + FileSystem::FormatFileSystem(FileSystem::Type::SaveData); + // TODO(Subv): Find out the correct error code for this. + rb.Push(ResultCode(ErrorModule::FS, 40)); + } else { + rb.Push(RESULT_SUCCESS); + } + rb.Push(0); } diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 32752aea5f..ef05955b95 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -43,6 +43,19 @@ ResultVal> OpenFileSystem(Type type, return itr->second->Open(path); } +ResultCode FormatFileSystem(Type type) { + LOG_TRACE(Service_FS, "Formatting FileSystem with type=%d", type); + + auto itr = filesystem_map.find(type); + if (itr == filesystem_map.end()) { + // TODO(bunnei): Find a better error code for this + return ResultCode(-1); + } + + FileSys::Path unused; + return itr->second->Format(unused); +} + void RegisterFileSystems() { filesystem_map.clear(); diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index 80f318676d..8d30e94a13 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h @@ -44,6 +44,13 @@ ResultCode RegisterFileSystem(std::unique_ptr&& fact ResultVal> OpenFileSystem(Type type, FileSys::Path& path); +/** + * Formats a file system + * @param type Type of the file system to format + * @return ResultCode of the operation + */ +ResultCode FormatFileSystem(Type type); + /// Registers all Filesystem services with the specified service manager. void InstallInterfaces(SM::ServiceManager& service_manager); From e4b7a1d160fd44dee82a86a4c186a29b19924f0d Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 4 Mar 2018 14:31:57 -0500 Subject: [PATCH 2/3] FS: Stubbed CreateSaveData. It currently does nothing. --- src/core/hle/service/filesystem/fsp_srv.cpp | 14 ++++++++++++++ src/core/hle/service/filesystem/fsp_srv.h | 1 + 2 files changed, 15 insertions(+) diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index 3ac5a96cb2..97b3fa290a 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -245,6 +245,7 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { static const FunctionInfo functions[] = { {1, &FSP_SRV::Initalize, "Initalize"}, {18, &FSP_SRV::MountSdCard, "MountSdCard"}, + {22, &FSP_SRV::CreateSaveData, "CreateSaveData"}, {51, &FSP_SRV::MountSaveData, "MountSaveData"}, {200, &FSP_SRV::OpenDataStorageByCurrentProcess, "OpenDataStorageByCurrentProcess"}, {202, nullptr, "OpenDataStorageByDataId"}, @@ -279,6 +280,19 @@ void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) { rb.Push(RESULT_SUCCESS); } +void FSP_SRV::CreateSaveData(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + auto save_struct = rp.PopRaw>(); + auto save_create_struct = rp.PopRaw>(); + u128 uid = rp.PopRaw(); + + LOG_WARNING(Service_FS, "(STUBBED) called uid = %016" PRIX64 "%016" PRIX64, uid[1], uid[0]); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_FS, "(STUBBED) called"); diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h index f19b2f2c43..e15ba43750 100644 --- a/src/core/hle/service/filesystem/fsp_srv.h +++ b/src/core/hle/service/filesystem/fsp_srv.h @@ -24,6 +24,7 @@ private: void Initalize(Kernel::HLERequestContext& ctx); void MountSdCard(Kernel::HLERequestContext& ctx); + void CreateSaveData(Kernel::HLERequestContext& ctx); void MountSaveData(Kernel::HLERequestContext& ctx); void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); From 84e1c0a43016e4c0e99aa50b1486af53b7d05513 Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 4 Mar 2018 14:34:48 -0500 Subject: [PATCH 3/3] FS: Use the correct error code when trying to open files that don't exist. --- src/core/file_sys/disk_filesystem.cpp | 7 +++---- src/core/file_sys/errors.h | 25 +++---------------------- 2 files changed, 6 insertions(+), 26 deletions(-) diff --git a/src/core/file_sys/disk_filesystem.cpp b/src/core/file_sys/disk_filesystem.cpp index be7574fdb3..22b17ba045 100644 --- a/src/core/file_sys/disk_filesystem.cpp +++ b/src/core/file_sys/disk_filesystem.cpp @@ -7,6 +7,7 @@ #include "common/common_types.h" #include "common/logging/log.h" #include "core/file_sys/disk_filesystem.h" +#include "core/file_sys/errors.h" namespace FileSys { @@ -22,8 +23,7 @@ ResultVal> Disk_FileSystem::OpenFile(const std:: auto file = std::make_shared(full_path, mode == Mode::Read ? "rb" : "wb"); if (!file->IsOpen()) { - // TODO(Subv): Find out the correct error code. - return ResultCode(-1); + return ERROR_PATH_NOT_FOUND; } return MakeResult>( @@ -100,8 +100,7 @@ u64 Disk_FileSystem::GetFreeSpaceSize() const { ResultVal Disk_FileSystem::GetEntryType(const std::string& path) const { std::string full_path = base_directory + path; if (!FileUtil::Exists(full_path)) { - // TODO(Subv): Find out what this actually means - return ResultCode(ErrorModule::FS, 1); + return ERROR_PATH_NOT_FOUND; } // TODO(Subv): Find out the EntryType values diff --git a/src/core/file_sys/errors.h b/src/core/file_sys/errors.h index be3224ef8a..0ed7d2a0ce 100644 --- a/src/core/file_sys/errors.h +++ b/src/core/file_sys/errors.h @@ -10,36 +10,17 @@ namespace FileSys { namespace ErrCodes { enum { - RomFSNotFound = 100, - ArchiveNotMounted = 101, - FileNotFound = 112, - PathNotFound = 113, - GameCardNotInserted = 141, - NotFound = 120, - FileAlreadyExists = 180, - DirectoryAlreadyExists = 185, - AlreadyExists = 190, - InvalidOpenFlags = 230, - DirectoryNotEmpty = 240, - NotAFile = 250, - NotFormatted = 340, ///< This is used by the FS service when creating a SaveData archive - ExeFSSectionNotFound = 567, - CommandNotAllowed = 630, - InvalidReadFlag = 700, - InvalidPath = 702, - WriteBeyondEnd = 705, - UnsupportedOpenFlags = 760, - IncorrectExeFSReadSize = 761, - UnexpectedFileOrDirectory = 770, + NotFound = 1, }; } +constexpr ResultCode ERROR_PATH_NOT_FOUND(ErrorModule::FS, ErrCodes::NotFound); + // TODO(bunnei): Replace these with correct errors for Switch OS constexpr ResultCode ERROR_INVALID_PATH(ResultCode(-1)); constexpr ResultCode ERROR_UNSUPPORTED_OPEN_FLAGS(ResultCode(-1)); constexpr ResultCode ERROR_INVALID_OPEN_FLAGS(ResultCode(-1)); constexpr ResultCode ERROR_FILE_NOT_FOUND(ResultCode(-1)); -constexpr ResultCode ERROR_PATH_NOT_FOUND(ResultCode(-1)); constexpr ResultCode ERROR_UNEXPECTED_FILE_OR_DIRECTORY(ResultCode(-1)); constexpr ResultCode ERROR_DIRECTORY_ALREADY_EXISTS(ResultCode(-1)); constexpr ResultCode ERROR_FILE_ALREADY_EXISTS(ResultCode(-1));