diff options
Diffstat (limited to 'src/core/hle')
35 files changed, 792 insertions, 627 deletions
diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 749f51f69..316370266 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -189,14 +189,14 @@ enum class ErrorModule : u32 {  union Result {      u32 raw; -    BitField<0, 9, ErrorModule> module; -    BitField<9, 13, u32> description; +    using Module = BitField<0, 9, ErrorModule>; +    using Description = BitField<9, 13, u32>;      Result() = default;      constexpr explicit Result(u32 raw_) : raw(raw_) {}      constexpr Result(ErrorModule module_, u32 description_) -        : raw(module.FormatValue(module_) | description.FormatValue(description_)) {} +        : raw(Module::FormatValue(module_) | Description::FormatValue(description_)) {}      [[nodiscard]] constexpr bool IsSuccess() const {          return raw == 0; @@ -211,7 +211,15 @@ union Result {      }      [[nodiscard]] constexpr u32 GetInnerValue() const { -        return static_cast<u32>(module.Value()) | (description << module.bits); +        return raw; +    } + +    [[nodiscard]] constexpr ErrorModule GetModule() const { +        return Module::ExtractValue(raw); +    } + +    [[nodiscard]] constexpr u32 GetDescription() const { +        return Description::ExtractValue(raw);      }      [[nodiscard]] constexpr bool Includes(Result result) const { @@ -274,8 +282,9 @@ public:      }      [[nodiscard]] constexpr bool Includes(Result other) const { -        return code.module == other.module && code.description <= other.description && -               other.description <= description_end; +        return code.GetModule() == other.GetModule() && +               code.GetDescription() <= other.GetDescription() && +               other.GetDescription() <= description_end;      }  private: @@ -330,6 +339,16 @@ constexpr bool EvaluateResultFailure(const Result& r) {      return R_FAILED(r);  } +template <auto... R> +constexpr bool EvaluateAnyResultIncludes(const Result& r) { +    return ((r == R) || ...); +} + +template <auto... R> +constexpr bool EvaluateResultNotIncluded(const Result& r) { +    return !EvaluateAnyResultIncludes<R...>(r); +} +  template <typename T>  constexpr void UpdateCurrentResultReference(T result_reference, Result result) = delete;  // Intentionally not defined @@ -371,6 +390,13 @@ constexpr void UpdateCurrentResultReference<const Result>(Result result_referenc      DECLARE_CURRENT_RESULT_REFERENCE_AND_STORAGE(__COUNTER__);                                     \      ON_RESULT_SUCCESS_2 +#define ON_RESULT_INCLUDED_2(...)                                                                  \ +    ON_RESULT_RETURN_IMPL(ResultImpl::EvaluateAnyResultIncludes<__VA_ARGS__>) + +#define ON_RESULT_INCLUDED(...)                                                                    \ +    DECLARE_CURRENT_RESULT_REFERENCE_AND_STORAGE(__COUNTER__);                                     \ +    ON_RESULT_INCLUDED_2(__VA_ARGS__) +  constexpr inline Result __TmpCurrentResultReference = ResultSuccess;  /// Returns a result. diff --git a/src/core/hle/service/am/applets/applet_error.cpp b/src/core/hle/service/am/applets/applet_error.cpp index 5d17c353f..084bc138c 100644 --- a/src/core/hle/service/am/applets/applet_error.cpp +++ b/src/core/hle/service/am/applets/applet_error.cpp @@ -27,8 +27,8 @@ struct ErrorCode {      static constexpr ErrorCode FromResult(Result result) {          return { -            .error_category{2000 + static_cast<u32>(result.module.Value())}, -            .error_number{result.description.Value()}, +            .error_category{2000 + static_cast<u32>(result.GetModule())}, +            .error_number{result.GetDescription()},          };      } diff --git a/src/core/hle/service/am/applets/applet_web_browser.cpp b/src/core/hle/service/am/applets/applet_web_browser.cpp index b0ea2b381..19057ad7b 100644 --- a/src/core/hle/service/am/applets/applet_web_browser.cpp +++ b/src/core/hle/service/am/applets/applet_web_browser.cpp @@ -9,13 +9,13 @@  #include "common/string_util.h"  #include "core/core.h"  #include "core/file_sys/content_archive.h" -#include "core/file_sys/mode.h" +#include "core/file_sys/fs_filesystem.h"  #include "core/file_sys/nca_metadata.h"  #include "core/file_sys/patch_manager.h"  #include "core/file_sys/registered_cache.h"  #include "core/file_sys/romfs.h"  #include "core/file_sys/system_archive/system_archive.h" -#include "core/file_sys/vfs_vector.h" +#include "core/file_sys/vfs/vfs_vector.h"  #include "core/frontend/applets/web_browser.h"  #include "core/hle/result.h"  #include "core/hle/service/am/am.h" @@ -213,7 +213,7 @@ void ExtractSharedFonts(Core::System& system) {              std::move(decrypted_data), DECRYPTED_SHARED_FONTS[i]);          const auto temp_dir = system.GetFilesystem()->CreateDirectory( -            Common::FS::PathToUTF8String(fonts_dir), FileSys::Mode::ReadWrite); +            Common::FS::PathToUTF8String(fonts_dir), FileSys::OpenMode::ReadWrite);          const auto out_file = temp_dir->CreateFile(DECRYPTED_SHARED_FONTS[i]); @@ -333,7 +333,7 @@ void WebBrowser::ExtractOfflineRomFS() {      const auto extracted_romfs_dir = FileSys::ExtractRomFS(offline_romfs);      const auto temp_dir = system.GetFilesystem()->CreateDirectory( -        Common::FS::PathToUTF8String(offline_cache_dir), FileSys::Mode::ReadWrite); +        Common::FS::PathToUTF8String(offline_cache_dir), FileSys::OpenMode::ReadWrite);      FileSys::VfsRawCopyD(extracted_romfs_dir, temp_dir);  } diff --git a/src/core/hle/service/am/applets/applet_web_browser.h b/src/core/hle/service/am/applets/applet_web_browser.h index 99fe18659..36adb2510 100644 --- a/src/core/hle/service/am/applets/applet_web_browser.h +++ b/src/core/hle/service/am/applets/applet_web_browser.h @@ -7,7 +7,7 @@  #include <optional>  #include "common/common_types.h" -#include "core/file_sys/vfs_types.h" +#include "core/file_sys/vfs/vfs_types.h"  #include "core/hle/result.h"  #include "core/hle/service/am/applets/applet_web_browser_types.h"  #include "core/hle/service/am/applets/applets.h" diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index bd4ca753b..05581e6e0 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp @@ -139,7 +139,8 @@ private:                  ctx.WriteBufferC(performance_buffer.data(), performance_buffer.size(), 1);              }          } else { -            LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!", result.description); +            LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!", +                      result.GetDescription());          }          IPC::ResponseBuilder rb{ctx, 2}; diff --git a/src/core/hle/service/bcat/backend/backend.h b/src/core/hle/service/bcat/backend/backend.h index 205ed0702..aa36d29d5 100644 --- a/src/core/hle/service/bcat/backend/backend.h +++ b/src/core/hle/service/bcat/backend/backend.h @@ -8,7 +8,7 @@  #include <string>  #include "common/common_types.h" -#include "core/file_sys/vfs_types.h" +#include "core/file_sys/vfs/vfs_types.h"  #include "core/hle/result.h"  #include "core/hle/service/kernel_helpers.h" diff --git a/src/core/hle/service/bcat/bcat_module.cpp b/src/core/hle/service/bcat/bcat_module.cpp index a6281913a..76d7bb139 100644 --- a/src/core/hle/service/bcat/bcat_module.cpp +++ b/src/core/hle/service/bcat/bcat_module.cpp @@ -8,7 +8,7 @@  #include "common/settings.h"  #include "common/string_util.h"  #include "core/core.h" -#include "core/file_sys/vfs.h" +#include "core/file_sys/vfs/vfs.h"  #include "core/hle/kernel/k_readable_event.h"  #include "core/hle/service/bcat/backend/backend.h"  #include "core/hle/service/bcat/bcat.h" diff --git a/src/core/hle/service/caps/caps_a.cpp b/src/core/hle/service/caps/caps_a.cpp index 9925720a3..69acb3a8b 100644 --- a/src/core/hle/service/caps/caps_a.cpp +++ b/src/core/hle/service/caps/caps_a.cpp @@ -202,14 +202,14 @@ Result IAlbumAccessorService::TranslateResult(Result in_result) {      }      if ((in_result.raw & 0x3801ff) == ResultUnknown1024.raw) { -        if (in_result.description - 0x514 < 100) { +        if (in_result.GetDescription() - 0x514 < 100) {              return ResultInvalidFileData;          } -        if (in_result.description - 0x5dc < 100) { +        if (in_result.GetDescription() - 0x5dc < 100) {              return ResultInvalidFileData;          } -        if (in_result.description - 0x578 < 100) { +        if (in_result.GetDescription() - 0x578 < 100) {              if (in_result == ResultFileCountLimit) {                  return ResultUnknown22;              } @@ -244,9 +244,10 @@ Result IAlbumAccessorService::TranslateResult(Result in_result) {          return ResultUnknown1024;      } -    if (in_result.module == ErrorModule::FS) { -        if ((in_result.description >> 0xc < 0x7d) || (in_result.description - 1000 < 2000) || -            (((in_result.description - 3000) >> 3) < 0x271)) { +    if (in_result.GetModule() == ErrorModule::FS) { +        if ((in_result.GetDescription() >> 0xc < 0x7d) || +            (in_result.GetDescription() - 1000 < 2000) || +            (((in_result.GetDescription() - 3000) >> 3) < 0x271)) {              // TODO: Translate FS error              return in_result;          } diff --git a/src/core/hle/service/fatal/fatal.cpp b/src/core/hle/service/fatal/fatal.cpp index 31da86074..dfcac1ffd 100644 --- a/src/core/hle/service/fatal/fatal.cpp +++ b/src/core/hle/service/fatal/fatal.cpp @@ -73,8 +73,8 @@ static void GenerateErrorReport(Core::System& system, Result error_code, const F          "Program entry point:             0x{:16X}\n"          "\n",          Common::g_scm_branch, Common::g_scm_desc, title_id, error_code.raw, -        2000 + static_cast<u32>(error_code.module.Value()), -        static_cast<u32>(error_code.description.Value()), info.set_flags, info.program_entry_point); +        2000 + static_cast<u32>(error_code.GetModule()), +        static_cast<u32>(error_code.GetDescription()), info.set_flags, info.program_entry_point);      if (info.backtrace_size != 0x0) {          crash_report += "Registers:\n";          for (size_t i = 0; i < info.registers.size(); i++) { diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index ca6d8d607..ae230afc0 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -12,18 +12,17 @@  #include "core/file_sys/card_image.h"  #include "core/file_sys/control_metadata.h"  #include "core/file_sys/errors.h" -#include "core/file_sys/mode.h"  #include "core/file_sys/patch_manager.h"  #include "core/file_sys/registered_cache.h"  #include "core/file_sys/romfs_factory.h"  #include "core/file_sys/savedata_factory.h"  #include "core/file_sys/sdmc_factory.h" -#include "core/file_sys/vfs.h" -#include "core/file_sys/vfs_offset.h" +#include "core/file_sys/vfs/vfs.h" +#include "core/file_sys/vfs/vfs_offset.h"  #include "core/hle/service/filesystem/filesystem.h" -#include "core/hle/service/filesystem/fsp_ldr.h" -#include "core/hle/service/filesystem/fsp_pr.h" -#include "core/hle/service/filesystem/fsp_srv.h" +#include "core/hle/service/filesystem/fsp/fsp_ldr.h" +#include "core/hle/service/filesystem/fsp/fsp_pr.h" +#include "core/hle/service/filesystem/fsp/fsp_srv.h"  #include "core/hle/service/filesystem/romfs_controller.h"  #include "core/hle/service/filesystem/save_data_controller.h"  #include "core/hle/service/server_manager.h" @@ -53,12 +52,12 @@ Result VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 size      std::string path(Common::FS::SanitizePath(path_));      auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path));      if (dir == nullptr) { -        return FileSys::ERROR_PATH_NOT_FOUND; +        return FileSys::ResultPathNotFound;      } -    FileSys::EntryType entry_type{}; +    FileSys::DirectoryEntryType entry_type{};      if (GetEntryType(&entry_type, path) == ResultSuccess) { -        return FileSys::ERROR_PATH_ALREADY_EXISTS; +        return FileSys::ResultPathAlreadyExists;      }      auto file = dir->CreateFile(Common::FS::GetFilename(path)); @@ -82,7 +81,7 @@ Result VfsDirectoryServiceWrapper::DeleteFile(const std::string& path_) const {      auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path));      if (dir == nullptr || dir->GetFile(Common::FS::GetFilename(path)) == nullptr) { -        return FileSys::ERROR_PATH_NOT_FOUND; +        return FileSys::ResultPathNotFound;      }      if (!dir->DeleteFile(Common::FS::GetFilename(path))) {          // TODO(DarkLordZach): Find a better error code for this @@ -153,12 +152,12 @@ Result VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path_,      if (Common::FS::GetParentPath(src_path) == Common::FS::GetParentPath(dest_path)) {          // Use more-optimized vfs implementation rename.          if (src == nullptr) { -            return FileSys::ERROR_PATH_NOT_FOUND; +            return FileSys::ResultPathNotFound;          }          if (dst && Common::FS::Exists(dst->GetFullPath())) {              LOG_ERROR(Service_FS, "File at new_path={} already exists", dst->GetFullPath()); -            return FileSys::ERROR_PATH_ALREADY_EXISTS; +            return FileSys::ResultPathAlreadyExists;          }          if (!src->Rename(Common::FS::GetFilename(dest_path))) { @@ -195,7 +194,7 @@ Result VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path_,      if (Common::FS::GetParentPath(src_path) == Common::FS::GetParentPath(dest_path)) {          // Use more-optimized vfs implementation rename.          if (src == nullptr) -            return FileSys::ERROR_PATH_NOT_FOUND; +            return FileSys::ResultPathNotFound;          if (!src->Rename(Common::FS::GetFilename(dest_path))) {              // TODO(DarkLordZach): Find a better error code for this              return ResultUnknown; @@ -214,7 +213,8 @@ Result VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path_,  }  Result VfsDirectoryServiceWrapper::OpenFile(FileSys::VirtualFile* out_file, -                                            const std::string& path_, FileSys::Mode mode) const { +                                            const std::string& path_, +                                            FileSys::OpenMode mode) const {      const std::string path(Common::FS::SanitizePath(path_));      std::string_view npath = path;      while (!npath.empty() && (npath[0] == '/' || npath[0] == '\\')) { @@ -223,10 +223,10 @@ Result VfsDirectoryServiceWrapper::OpenFile(FileSys::VirtualFile* out_file,      auto file = backing->GetFileRelative(npath);      if (file == nullptr) { -        return FileSys::ERROR_PATH_NOT_FOUND; +        return FileSys::ResultPathNotFound;      } -    if (mode == FileSys::Mode::Append) { +    if (mode == FileSys::OpenMode::AllowAppend) {          *out_file = std::make_shared<FileSys::OffsetVfsFile>(file, 0, file->GetSize());      } else {          *out_file = file; @@ -241,50 +241,50 @@ Result VfsDirectoryServiceWrapper::OpenDirectory(FileSys::VirtualDir* out_direct      auto dir = GetDirectoryRelativeWrapped(backing, path);      if (dir == nullptr) {          // TODO(DarkLordZach): Find a better error code for this -        return FileSys::ERROR_PATH_NOT_FOUND; +        return FileSys::ResultPathNotFound;      }      *out_directory = dir;      return ResultSuccess;  } -Result VfsDirectoryServiceWrapper::GetEntryType(FileSys::EntryType* out_entry_type, +Result VfsDirectoryServiceWrapper::GetEntryType(FileSys::DirectoryEntryType* out_entry_type,                                                  const std::string& path_) const {      std::string path(Common::FS::SanitizePath(path_));      auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path));      if (dir == nullptr) { -        return FileSys::ERROR_PATH_NOT_FOUND; +        return FileSys::ResultPathNotFound;      }      auto filename = Common::FS::GetFilename(path);      // TODO(Subv): Some games use the '/' path, find out what this means.      if (filename.empty()) { -        *out_entry_type = FileSys::EntryType::Directory; +        *out_entry_type = FileSys::DirectoryEntryType::Directory;          return ResultSuccess;      }      if (dir->GetFile(filename) != nullptr) { -        *out_entry_type = FileSys::EntryType::File; +        *out_entry_type = FileSys::DirectoryEntryType::File;          return ResultSuccess;      }      if (dir->GetSubdirectory(filename) != nullptr) { -        *out_entry_type = FileSys::EntryType::Directory; +        *out_entry_type = FileSys::DirectoryEntryType::Directory;          return ResultSuccess;      } -    return FileSys::ERROR_PATH_NOT_FOUND; +    return FileSys::ResultPathNotFound;  }  Result VfsDirectoryServiceWrapper::GetFileTimeStampRaw(      FileSys::FileTimeStampRaw* out_file_time_stamp_raw, const std::string& path) const {      auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path));      if (dir == nullptr) { -        return FileSys::ERROR_PATH_NOT_FOUND; +        return FileSys::ResultPathNotFound;      } -    FileSys::EntryType entry_type; +    FileSys::DirectoryEntryType entry_type;      if (GetEntryType(&entry_type, path) != ResultSuccess) { -        return FileSys::ERROR_PATH_NOT_FOUND; +        return FileSys::ResultPathNotFound;      }      *out_file_time_stamp_raw = dir->GetFileTimeStamp(Common::FS::GetFilename(path)); @@ -317,7 +317,7 @@ Result FileSystemController::OpenProcess(      const auto it = registrations.find(process_id);      if (it == registrations.end()) { -        return FileSys::ERROR_ENTITY_NOT_FOUND; +        return FileSys::ResultTargetNotFound;      }      *out_program_id = it->second.program_id; @@ -347,7 +347,7 @@ std::shared_ptr<SaveDataController> FileSystemController::OpenSaveDataController  std::shared_ptr<FileSys::SaveDataFactory> FileSystemController::CreateSaveDataFactory(      ProgramId program_id) {      using YuzuPath = Common::FS::YuzuPath; -    const auto rw_mode = FileSys::Mode::ReadWrite; +    const auto rw_mode = FileSys::OpenMode::ReadWrite;      auto vfs = system.GetFilesystem();      const auto nand_directory = @@ -360,12 +360,12 @@ Result FileSystemController::OpenSDMC(FileSys::VirtualDir* out_sdmc) const {      LOG_TRACE(Service_FS, "Opening SDMC");      if (sdmc_factory == nullptr) { -        return FileSys::ERROR_SD_CARD_NOT_FOUND; +        return FileSys::ResultPortSdCardNoDevice;      }      auto sdmc = sdmc_factory->Open();      if (sdmc == nullptr) { -        return FileSys::ERROR_SD_CARD_NOT_FOUND; +        return FileSys::ResultPortSdCardNoDevice;      }      *out_sdmc = sdmc; @@ -377,12 +377,12 @@ Result FileSystemController::OpenBISPartition(FileSys::VirtualDir* out_bis_parti      LOG_TRACE(Service_FS, "Opening BIS Partition with id={:08X}", id);      if (bis_factory == nullptr) { -        return FileSys::ERROR_ENTITY_NOT_FOUND; +        return FileSys::ResultTargetNotFound;      }      auto part = bis_factory->OpenPartition(id);      if (part == nullptr) { -        return FileSys::ERROR_INVALID_ARGUMENT; +        return FileSys::ResultInvalidArgument;      }      *out_bis_partition = part; @@ -394,12 +394,12 @@ Result FileSystemController::OpenBISPartitionStorage(      LOG_TRACE(Service_FS, "Opening BIS Partition Storage with id={:08X}", id);      if (bis_factory == nullptr) { -        return FileSys::ERROR_ENTITY_NOT_FOUND; +        return FileSys::ResultTargetNotFound;      }      auto part = bis_factory->OpenPartitionStorage(id, system.GetFilesystem());      if (part == nullptr) { -        return FileSys::ERROR_INVALID_ARGUMENT; +        return FileSys::ResultInvalidArgument;      }      *out_bis_partition_storage = part; @@ -686,15 +686,15 @@ void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool ove      using YuzuPath = Common::FS::YuzuPath;      const auto sdmc_dir_path = Common::FS::GetYuzuPath(YuzuPath::SDMCDir);      const auto sdmc_load_dir_path = sdmc_dir_path / "atmosphere/contents"; -    const auto rw_mode = FileSys::Mode::ReadWrite; +    const auto rw_mode = FileSys::OpenMode::ReadWrite;      auto nand_directory =          vfs.OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::NANDDir), rw_mode);      auto sd_directory = vfs.OpenDirectory(Common::FS::PathToUTF8String(sdmc_dir_path), rw_mode); -    auto load_directory = -        vfs.OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::LoadDir), FileSys::Mode::Read); -    auto sd_load_directory = -        vfs.OpenDirectory(Common::FS::PathToUTF8String(sdmc_load_dir_path), FileSys::Mode::Read); +    auto load_directory = vfs.OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::LoadDir), +                                            FileSys::OpenMode::Read); +    auto sd_load_directory = vfs.OpenDirectory(Common::FS::PathToUTF8String(sdmc_load_dir_path), +                                               FileSys::OpenMode::Read);      auto dump_directory =          vfs.OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::DumpDir), rw_mode); diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index 48f37d289..718500385 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h @@ -4,9 +4,11 @@  #pragma once  #include <memory> +#include <mutex>  #include "common/common_types.h" -#include "core/file_sys/directory.h" -#include "core/file_sys/vfs.h" +#include "core/file_sys/fs_directory.h" +#include "core/file_sys/fs_filesystem.h" +#include "core/file_sys/vfs/vfs.h"  #include "core/hle/result.h"  namespace Core { @@ -26,7 +28,6 @@ class XCI;  enum class BisPartitionId : u32;  enum class ContentRecordType : u8; -enum class Mode : u32;  enum class SaveDataSpaceId : u8;  enum class SaveDataType : u8;  enum class StorageId : u8; @@ -57,13 +58,6 @@ enum class ImageDirectoryId : u32 {      SdCard,  }; -enum class OpenDirectoryMode : u64 { -    Directory = (1 << 0), -    File = (1 << 1), -    All = Directory | File -}; -DECLARE_ENUM_FLAG_OPERATORS(OpenDirectoryMode); -  using ProcessId = u64;  using ProgramId = u64; @@ -237,7 +231,7 @@ public:       * @return Opened file, or error code       */      Result OpenFile(FileSys::VirtualFile* out_file, const std::string& path, -                    FileSys::Mode mode) const; +                    FileSys::OpenMode mode) const;      /**       * Open a directory specified by its path @@ -250,7 +244,7 @@ public:       * Get the type of the specified path       * @return The type of the specified path or error code       */ -    Result GetEntryType(FileSys::EntryType* out_entry_type, const std::string& path) const; +    Result GetEntryType(FileSys::DirectoryEntryType* out_entry_type, const std::string& path) const;      /**       * Get the timestamp of the specified path diff --git a/src/core/hle/service/filesystem/fsp/fs_i_directory.cpp b/src/core/hle/service/filesystem/fsp/fs_i_directory.cpp new file mode 100644 index 000000000..39690018b --- /dev/null +++ b/src/core/hle/service/filesystem/fsp/fs_i_directory.cpp @@ -0,0 +1,84 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/file_sys/fs_filesystem.h" +#include "core/file_sys/savedata_factory.h" +#include "core/hle/service/filesystem/fsp/fs_i_directory.h" +#include "core/hle/service/ipc_helpers.h" + +namespace Service::FileSystem { + +template <typename T> +static void BuildEntryIndex(std::vector<FileSys::DirectoryEntry>& entries, +                            const std::vector<T>& new_data, FileSys::DirectoryEntryType type) { +    entries.reserve(entries.size() + new_data.size()); + +    for (const auto& new_entry : new_data) { +        auto name = new_entry->GetName(); + +        if (type == FileSys::DirectoryEntryType::File && +            name == FileSys::GetSaveDataSizeFileName()) { +            continue; +        } + +        entries.emplace_back(name, static_cast<s8>(type), +                             type == FileSys::DirectoryEntryType::Directory ? 0 +                                                                            : new_entry->GetSize()); +    } +} + +IDirectory::IDirectory(Core::System& system_, FileSys::VirtualDir backend_, +                       FileSys::OpenDirectoryMode mode) +    : ServiceFramework{system_, "IDirectory"}, backend(std::move(backend_)) { +    static const FunctionInfo functions[] = { +        {0, &IDirectory::Read, "Read"}, +        {1, &IDirectory::GetEntryCount, "GetEntryCount"}, +    }; +    RegisterHandlers(functions); + +    // TODO(DarkLordZach): Verify that this is the correct behavior. +    // Build entry index now to save time later. +    if (True(mode & FileSys::OpenDirectoryMode::Directory)) { +        BuildEntryIndex(entries, backend->GetSubdirectories(), +                        FileSys::DirectoryEntryType::Directory); +    } +    if (True(mode & FileSys::OpenDirectoryMode::File)) { +        BuildEntryIndex(entries, backend->GetFiles(), FileSys::DirectoryEntryType::File); +    } +} + +void IDirectory::Read(HLERequestContext& ctx) { +    LOG_DEBUG(Service_FS, "called."); + +    // Calculate how many entries we can fit in the output buffer +    const u64 count_entries = ctx.GetWriteBufferNumElements<FileSys::DirectoryEntry>(); + +    // Cap at total number of entries. +    const u64 actual_entries = std::min(count_entries, entries.size() - next_entry_index); + +    // Determine data start and end +    const auto* begin = reinterpret_cast<u8*>(entries.data() + next_entry_index); +    const auto* end = reinterpret_cast<u8*>(entries.data() + next_entry_index + actual_entries); +    const auto range_size = static_cast<std::size_t>(std::distance(begin, end)); + +    next_entry_index += actual_entries; + +    // Write the data to memory +    ctx.WriteBuffer(begin, range_size); + +    IPC::ResponseBuilder rb{ctx, 4}; +    rb.Push(ResultSuccess); +    rb.Push(actual_entries); +} + +void IDirectory::GetEntryCount(HLERequestContext& ctx) { +    LOG_DEBUG(Service_FS, "called"); + +    u64 count = entries.size() - next_entry_index; + +    IPC::ResponseBuilder rb{ctx, 4}; +    rb.Push(ResultSuccess); +    rb.Push(count); +} + +} // namespace Service::FileSystem diff --git a/src/core/hle/service/filesystem/fsp/fs_i_directory.h b/src/core/hle/service/filesystem/fsp/fs_i_directory.h new file mode 100644 index 000000000..793ecfcd7 --- /dev/null +++ b/src/core/hle/service/filesystem/fsp/fs_i_directory.h @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/file_sys/vfs/vfs.h" +#include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/service.h" + +namespace FileSys { +struct DirectoryEntry; +} + +namespace Service::FileSystem { + +class IDirectory final : public ServiceFramework<IDirectory> { +public: +    explicit IDirectory(Core::System& system_, FileSys::VirtualDir backend_, +                        FileSys::OpenDirectoryMode mode); + +private: +    FileSys::VirtualDir backend; +    std::vector<FileSys::DirectoryEntry> entries; +    u64 next_entry_index = 0; + +    void Read(HLERequestContext& ctx); +    void GetEntryCount(HLERequestContext& ctx); +}; + +} // namespace Service::FileSystem diff --git a/src/core/hle/service/filesystem/fsp/fs_i_file.cpp b/src/core/hle/service/filesystem/fsp/fs_i_file.cpp new file mode 100644 index 000000000..9a18f6ec5 --- /dev/null +++ b/src/core/hle/service/filesystem/fsp/fs_i_file.cpp @@ -0,0 +1,127 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/file_sys/errors.h" +#include "core/hle/service/filesystem/fsp/fs_i_file.h" +#include "core/hle/service/ipc_helpers.h" + +namespace Service::FileSystem { + +IFile::IFile(Core::System& system_, FileSys::VirtualFile backend_) +    : ServiceFramework{system_, "IFile"}, backend(std::move(backend_)) { +    static const FunctionInfo functions[] = { +        {0, &IFile::Read, "Read"}, +        {1, &IFile::Write, "Write"}, +        {2, &IFile::Flush, "Flush"}, +        {3, &IFile::SetSize, "SetSize"}, +        {4, &IFile::GetSize, "GetSize"}, +        {5, nullptr, "OperateRange"}, +        {6, nullptr, "OperateRangeWithBuffer"}, +    }; +    RegisterHandlers(functions); +} + +void IFile::Read(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const u64 option = rp.Pop<u64>(); +    const s64 offset = rp.Pop<s64>(); +    const s64 length = rp.Pop<s64>(); + +    LOG_DEBUG(Service_FS, "called, option={}, offset=0x{:X}, length={}", option, offset, length); + +    // Error checking +    if (length < 0) { +        LOG_ERROR(Service_FS, "Length is less than 0, length={}", length); +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(FileSys::ResultInvalidSize); +        return; +    } +    if (offset < 0) { +        LOG_ERROR(Service_FS, "Offset is less than 0, offset={}", offset); +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(FileSys::ResultInvalidOffset); +        return; +    } + +    // Read the data from the Storage backend +    std::vector<u8> output = backend->ReadBytes(length, offset); + +    // Write the data to memory +    ctx.WriteBuffer(output); + +    IPC::ResponseBuilder rb{ctx, 4}; +    rb.Push(ResultSuccess); +    rb.Push(static_cast<u64>(output.size())); +} + +void IFile::Write(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const u64 option = rp.Pop<u64>(); +    const s64 offset = rp.Pop<s64>(); +    const s64 length = rp.Pop<s64>(); + +    LOG_DEBUG(Service_FS, "called, option={}, offset=0x{:X}, length={}", option, offset, length); + +    // Error checking +    if (length < 0) { +        LOG_ERROR(Service_FS, "Length is less than 0, length={}", length); +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(FileSys::ResultInvalidSize); +        return; +    } +    if (offset < 0) { +        LOG_ERROR(Service_FS, "Offset is less than 0, offset={}", offset); +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(FileSys::ResultInvalidOffset); +        return; +    } + +    const auto data = ctx.ReadBuffer(); + +    ASSERT_MSG(static_cast<s64>(data.size()) <= length, +               "Attempting to write more data than requested (requested={:016X}, actual={:016X}).", +               length, data.size()); + +    // Write the data to the Storage backend +    const auto write_size = +        static_cast<std::size_t>(std::distance(data.begin(), data.begin() + length)); +    const std::size_t written = backend->Write(data.data(), write_size, offset); + +    ASSERT_MSG(static_cast<s64>(written) == length, +               "Could not write all bytes to file (requested={:016X}, actual={:016X}).", length, +               written); + +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(ResultSuccess); +} + +void IFile::Flush(HLERequestContext& ctx) { +    LOG_DEBUG(Service_FS, "called"); + +    // Exists for SDK compatibiltity -- No need to flush file. + +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(ResultSuccess); +} + +void IFile::SetSize(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const u64 size = rp.Pop<u64>(); +    LOG_DEBUG(Service_FS, "called, size={}", size); + +    backend->Resize(size); + +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(ResultSuccess); +} + +void IFile::GetSize(HLERequestContext& ctx) { +    const u64 size = backend->GetSize(); +    LOG_DEBUG(Service_FS, "called, size={}", size); + +    IPC::ResponseBuilder rb{ctx, 4}; +    rb.Push(ResultSuccess); +    rb.Push<u64>(size); +} + +} // namespace Service::FileSystem diff --git a/src/core/hle/service/filesystem/fsp/fs_i_file.h b/src/core/hle/service/filesystem/fsp/fs_i_file.h new file mode 100644 index 000000000..5e5430c67 --- /dev/null +++ b/src/core/hle/service/filesystem/fsp/fs_i_file.h @@ -0,0 +1,25 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/service.h" + +namespace Service::FileSystem { + +class IFile final : public ServiceFramework<IFile> { +public: +    explicit IFile(Core::System& system_, FileSys::VirtualFile backend_); + +private: +    FileSys::VirtualFile backend; + +    void Read(HLERequestContext& ctx); +    void Write(HLERequestContext& ctx); +    void Flush(HLERequestContext& ctx); +    void SetSize(HLERequestContext& ctx); +    void GetSize(HLERequestContext& ctx); +}; + +} // namespace Service::FileSystem diff --git a/src/core/hle/service/filesystem/fsp/fs_i_filesystem.cpp b/src/core/hle/service/filesystem/fsp/fs_i_filesystem.cpp new file mode 100644 index 000000000..efa394dd1 --- /dev/null +++ b/src/core/hle/service/filesystem/fsp/fs_i_filesystem.cpp @@ -0,0 +1,262 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/string_util.h" +#include "core/hle/service/filesystem/fsp/fs_i_directory.h" +#include "core/hle/service/filesystem/fsp/fs_i_file.h" +#include "core/hle/service/filesystem/fsp/fs_i_filesystem.h" +#include "core/hle/service/ipc_helpers.h" + +namespace Service::FileSystem { + +IFileSystem::IFileSystem(Core::System& system_, FileSys::VirtualDir backend_, SizeGetter size_) +    : ServiceFramework{system_, "IFileSystem"}, backend{std::move(backend_)}, size{std::move( +                                                                                  size_)} { +    static const FunctionInfo functions[] = { +        {0, &IFileSystem::CreateFile, "CreateFile"}, +        {1, &IFileSystem::DeleteFile, "DeleteFile"}, +        {2, &IFileSystem::CreateDirectory, "CreateDirectory"}, +        {3, &IFileSystem::DeleteDirectory, "DeleteDirectory"}, +        {4, &IFileSystem::DeleteDirectoryRecursively, "DeleteDirectoryRecursively"}, +        {5, &IFileSystem::RenameFile, "RenameFile"}, +        {6, nullptr, "RenameDirectory"}, +        {7, &IFileSystem::GetEntryType, "GetEntryType"}, +        {8, &IFileSystem::OpenFile, "OpenFile"}, +        {9, &IFileSystem::OpenDirectory, "OpenDirectory"}, +        {10, &IFileSystem::Commit, "Commit"}, +        {11, &IFileSystem::GetFreeSpaceSize, "GetFreeSpaceSize"}, +        {12, &IFileSystem::GetTotalSpaceSize, "GetTotalSpaceSize"}, +        {13, &IFileSystem::CleanDirectoryRecursively, "CleanDirectoryRecursively"}, +        {14, &IFileSystem::GetFileTimeStampRaw, "GetFileTimeStampRaw"}, +        {15, nullptr, "QueryEntry"}, +        {16, &IFileSystem::GetFileSystemAttribute, "GetFileSystemAttribute"}, +    }; +    RegisterHandlers(functions); +} + +void IFileSystem::CreateFile(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; + +    const auto file_buffer = ctx.ReadBuffer(); +    const std::string name = Common::StringFromBuffer(file_buffer); + +    const u64 file_mode = rp.Pop<u64>(); +    const u32 file_size = rp.Pop<u32>(); + +    LOG_DEBUG(Service_FS, "called. file={}, mode=0x{:X}, size=0x{:08X}", name, file_mode, +              file_size); + +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(backend.CreateFile(name, file_size)); +} + +void IFileSystem::DeleteFile(HLERequestContext& ctx) { +    const auto file_buffer = ctx.ReadBuffer(); +    const std::string name = Common::StringFromBuffer(file_buffer); + +    LOG_DEBUG(Service_FS, "called. file={}", name); + +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(backend.DeleteFile(name)); +} + +void IFileSystem::CreateDirectory(HLERequestContext& ctx) { +    const auto file_buffer = ctx.ReadBuffer(); +    const std::string name = Common::StringFromBuffer(file_buffer); + +    LOG_DEBUG(Service_FS, "called. directory={}", name); + +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(backend.CreateDirectory(name)); +} + +void IFileSystem::DeleteDirectory(HLERequestContext& ctx) { +    const auto file_buffer = ctx.ReadBuffer(); +    const std::string name = Common::StringFromBuffer(file_buffer); + +    LOG_DEBUG(Service_FS, "called. directory={}", name); + +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(backend.DeleteDirectory(name)); +} + +void IFileSystem::DeleteDirectoryRecursively(HLERequestContext& ctx) { +    const auto file_buffer = ctx.ReadBuffer(); +    const std::string name = Common::StringFromBuffer(file_buffer); + +    LOG_DEBUG(Service_FS, "called. directory={}", name); + +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(backend.DeleteDirectoryRecursively(name)); +} + +void IFileSystem::CleanDirectoryRecursively(HLERequestContext& ctx) { +    const auto file_buffer = ctx.ReadBuffer(); +    const std::string name = Common::StringFromBuffer(file_buffer); + +    LOG_DEBUG(Service_FS, "called. Directory: {}", name); + +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(backend.CleanDirectoryRecursively(name)); +} + +void IFileSystem::RenameFile(HLERequestContext& ctx) { +    const std::string src_name = Common::StringFromBuffer(ctx.ReadBuffer(0)); +    const std::string dst_name = Common::StringFromBuffer(ctx.ReadBuffer(1)); + +    LOG_DEBUG(Service_FS, "called. file '{}' to file '{}'", src_name, dst_name); + +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(backend.RenameFile(src_name, dst_name)); +} + +void IFileSystem::OpenFile(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; + +    const auto file_buffer = ctx.ReadBuffer(); +    const std::string name = Common::StringFromBuffer(file_buffer); + +    const auto mode = static_cast<FileSys::OpenMode>(rp.Pop<u32>()); + +    LOG_DEBUG(Service_FS, "called. file={}, mode={}", name, mode); + +    FileSys::VirtualFile vfs_file{}; +    auto result = backend.OpenFile(&vfs_file, name, mode); +    if (result != ResultSuccess) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(result); +        return; +    } + +    auto file = std::make_shared<IFile>(system, vfs_file); + +    IPC::ResponseBuilder rb{ctx, 2, 0, 1}; +    rb.Push(ResultSuccess); +    rb.PushIpcInterface<IFile>(std::move(file)); +} + +void IFileSystem::OpenDirectory(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; + +    const auto file_buffer = ctx.ReadBuffer(); +    const std::string name = Common::StringFromBuffer(file_buffer); +    const auto mode = rp.PopRaw<FileSys::OpenDirectoryMode>(); + +    LOG_DEBUG(Service_FS, "called. directory={}, mode={}", name, mode); + +    FileSys::VirtualDir vfs_dir{}; +    auto result = backend.OpenDirectory(&vfs_dir, name); +    if (result != ResultSuccess) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(result); +        return; +    } + +    auto directory = std::make_shared<IDirectory>(system, vfs_dir, mode); + +    IPC::ResponseBuilder rb{ctx, 2, 0, 1}; +    rb.Push(ResultSuccess); +    rb.PushIpcInterface<IDirectory>(std::move(directory)); +} + +void IFileSystem::GetEntryType(HLERequestContext& ctx) { +    const auto file_buffer = ctx.ReadBuffer(); +    const std::string name = Common::StringFromBuffer(file_buffer); + +    LOG_DEBUG(Service_FS, "called. file={}", name); + +    FileSys::DirectoryEntryType vfs_entry_type{}; +    auto result = backend.GetEntryType(&vfs_entry_type, name); +    if (result != ResultSuccess) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(result); +        return; +    } + +    IPC::ResponseBuilder rb{ctx, 3}; +    rb.Push(ResultSuccess); +    rb.Push<u32>(static_cast<u32>(vfs_entry_type)); +} + +void IFileSystem::Commit(HLERequestContext& ctx) { +    LOG_WARNING(Service_FS, "(STUBBED) called"); + +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(ResultSuccess); +} + +void IFileSystem::GetFreeSpaceSize(HLERequestContext& ctx) { +    LOG_DEBUG(Service_FS, "called"); + +    IPC::ResponseBuilder rb{ctx, 4}; +    rb.Push(ResultSuccess); +    rb.Push(size.get_free_size()); +} + +void IFileSystem::GetTotalSpaceSize(HLERequestContext& ctx) { +    LOG_DEBUG(Service_FS, "called"); + +    IPC::ResponseBuilder rb{ctx, 4}; +    rb.Push(ResultSuccess); +    rb.Push(size.get_total_size()); +} + +void IFileSystem::GetFileTimeStampRaw(HLERequestContext& ctx) { +    const auto file_buffer = ctx.ReadBuffer(); +    const std::string name = Common::StringFromBuffer(file_buffer); + +    LOG_WARNING(Service_FS, "(Partial Implementation) called. file={}", name); + +    FileSys::FileTimeStampRaw vfs_timestamp{}; +    auto result = backend.GetFileTimeStampRaw(&vfs_timestamp, name); +    if (result != ResultSuccess) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(result); +        return; +    } + +    IPC::ResponseBuilder rb{ctx, 10}; +    rb.Push(ResultSuccess); +    rb.PushRaw(vfs_timestamp); +} + +void IFileSystem::GetFileSystemAttribute(HLERequestContext& ctx) { +    LOG_WARNING(Service_FS, "(STUBBED) called"); + +    struct FileSystemAttribute { +        u8 dir_entry_name_length_max_defined; +        u8 file_entry_name_length_max_defined; +        u8 dir_path_name_length_max_defined; +        u8 file_path_name_length_max_defined; +        INSERT_PADDING_BYTES_NOINIT(0x5); +        u8 utf16_dir_entry_name_length_max_defined; +        u8 utf16_file_entry_name_length_max_defined; +        u8 utf16_dir_path_name_length_max_defined; +        u8 utf16_file_path_name_length_max_defined; +        INSERT_PADDING_BYTES_NOINIT(0x18); +        s32 dir_entry_name_length_max; +        s32 file_entry_name_length_max; +        s32 dir_path_name_length_max; +        s32 file_path_name_length_max; +        INSERT_PADDING_WORDS_NOINIT(0x5); +        s32 utf16_dir_entry_name_length_max; +        s32 utf16_file_entry_name_length_max; +        s32 utf16_dir_path_name_length_max; +        s32 utf16_file_path_name_length_max; +        INSERT_PADDING_WORDS_NOINIT(0x18); +        INSERT_PADDING_WORDS_NOINIT(0x1); +    }; +    static_assert(sizeof(FileSystemAttribute) == 0xc0, "FileSystemAttribute has incorrect size"); + +    FileSystemAttribute savedata_attribute{}; +    savedata_attribute.dir_entry_name_length_max_defined = true; +    savedata_attribute.file_entry_name_length_max_defined = true; +    savedata_attribute.dir_entry_name_length_max = 0x40; +    savedata_attribute.file_entry_name_length_max = 0x40; + +    IPC::ResponseBuilder rb{ctx, 50}; +    rb.Push(ResultSuccess); +    rb.PushRaw(savedata_attribute); +} + +} // namespace Service::FileSystem diff --git a/src/core/hle/service/filesystem/fsp/fs_i_filesystem.h b/src/core/hle/service/filesystem/fsp/fs_i_filesystem.h new file mode 100644 index 000000000..b06b3ef0e --- /dev/null +++ b/src/core/hle/service/filesystem/fsp/fs_i_filesystem.h @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/file_sys/vfs/vfs.h" +#include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/filesystem/fsp/fsp_util.h" +#include "core/hle/service/service.h" + +namespace Service::FileSystem { + +class IFileSystem final : public ServiceFramework<IFileSystem> { +public: +    explicit IFileSystem(Core::System& system_, FileSys::VirtualDir backend_, SizeGetter size_); + +    void CreateFile(HLERequestContext& ctx); +    void DeleteFile(HLERequestContext& ctx); +    void CreateDirectory(HLERequestContext& ctx); +    void DeleteDirectory(HLERequestContext& ctx); +    void DeleteDirectoryRecursively(HLERequestContext& ctx); +    void CleanDirectoryRecursively(HLERequestContext& ctx); +    void RenameFile(HLERequestContext& ctx); +    void OpenFile(HLERequestContext& ctx); +    void OpenDirectory(HLERequestContext& ctx); +    void GetEntryType(HLERequestContext& ctx); +    void Commit(HLERequestContext& ctx); +    void GetFreeSpaceSize(HLERequestContext& ctx); +    void GetTotalSpaceSize(HLERequestContext& ctx); +    void GetFileTimeStampRaw(HLERequestContext& ctx); +    void GetFileSystemAttribute(HLERequestContext& ctx); + +private: +    VfsDirectoryServiceWrapper backend; +    SizeGetter size; +}; + +} // namespace Service::FileSystem diff --git a/src/core/hle/service/filesystem/fsp/fs_i_storage.cpp b/src/core/hle/service/filesystem/fsp/fs_i_storage.cpp new file mode 100644 index 000000000..98223c1f9 --- /dev/null +++ b/src/core/hle/service/filesystem/fsp/fs_i_storage.cpp @@ -0,0 +1,62 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/file_sys/errors.h" +#include "core/hle/service/filesystem/fsp/fs_i_storage.h" +#include "core/hle/service/ipc_helpers.h" + +namespace Service::FileSystem { + +IStorage::IStorage(Core::System& system_, FileSys::VirtualFile backend_) +    : ServiceFramework{system_, "IStorage"}, backend(std::move(backend_)) { +    static const FunctionInfo functions[] = { +        {0, &IStorage::Read, "Read"}, +        {1, nullptr, "Write"}, +        {2, nullptr, "Flush"}, +        {3, nullptr, "SetSize"}, +        {4, &IStorage::GetSize, "GetSize"}, +        {5, nullptr, "OperateRange"}, +    }; +    RegisterHandlers(functions); +} + +void IStorage::Read(HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const s64 offset = rp.Pop<s64>(); +    const s64 length = rp.Pop<s64>(); + +    LOG_DEBUG(Service_FS, "called, offset=0x{:X}, length={}", offset, length); + +    // Error checking +    if (length < 0) { +        LOG_ERROR(Service_FS, "Length is less than 0, length={}", length); +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(FileSys::ResultInvalidSize); +        return; +    } +    if (offset < 0) { +        LOG_ERROR(Service_FS, "Offset is less than 0, offset={}", offset); +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(FileSys::ResultInvalidOffset); +        return; +    } + +    // Read the data from the Storage backend +    std::vector<u8> output = backend->ReadBytes(length, offset); +    // Write the data to memory +    ctx.WriteBuffer(output); + +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(ResultSuccess); +} + +void IStorage::GetSize(HLERequestContext& ctx) { +    const u64 size = backend->GetSize(); +    LOG_DEBUG(Service_FS, "called, size={}", size); + +    IPC::ResponseBuilder rb{ctx, 4}; +    rb.Push(ResultSuccess); +    rb.Push<u64>(size); +} + +} // namespace Service::FileSystem diff --git a/src/core/hle/service/filesystem/fsp/fs_i_storage.h b/src/core/hle/service/filesystem/fsp/fs_i_storage.h new file mode 100644 index 000000000..cb5bebcc9 --- /dev/null +++ b/src/core/hle/service/filesystem/fsp/fs_i_storage.h @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/file_sys/vfs/vfs.h" +#include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/service.h" + +namespace Service::FileSystem { + +class IStorage final : public ServiceFramework<IStorage> { +public: +    explicit IStorage(Core::System& system_, FileSys::VirtualFile backend_); + +private: +    FileSys::VirtualFile backend; + +    void Read(HLERequestContext& ctx); +    void GetSize(HLERequestContext& ctx); +}; + +} // namespace Service::FileSystem diff --git a/src/core/hle/service/filesystem/fsp_ldr.cpp b/src/core/hle/service/filesystem/fsp/fsp_ldr.cpp index 1e3366e71..8ee733f47 100644 --- a/src/core/hle/service/filesystem/fsp_ldr.cpp +++ b/src/core/hle/service/filesystem/fsp/fsp_ldr.cpp @@ -1,7 +1,7 @@  // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project  // SPDX-License-Identifier: GPL-2.0-or-later -#include "core/hle/service/filesystem/fsp_ldr.h" +#include "core/hle/service/filesystem/fsp/fsp_ldr.h"  namespace Service::FileSystem { diff --git a/src/core/hle/service/filesystem/fsp_ldr.h b/src/core/hle/service/filesystem/fsp/fsp_ldr.h index 358739a87..358739a87 100644 --- a/src/core/hle/service/filesystem/fsp_ldr.h +++ b/src/core/hle/service/filesystem/fsp/fsp_ldr.h diff --git a/src/core/hle/service/filesystem/fsp_pr.cpp b/src/core/hle/service/filesystem/fsp/fsp_pr.cpp index 4ffc31977..7c03ebaea 100644 --- a/src/core/hle/service/filesystem/fsp_pr.cpp +++ b/src/core/hle/service/filesystem/fsp/fsp_pr.cpp @@ -1,7 +1,7 @@  // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project  // SPDX-License-Identifier: GPL-2.0-or-later -#include "core/hle/service/filesystem/fsp_pr.h" +#include "core/hle/service/filesystem/fsp/fsp_pr.h"  namespace Service::FileSystem { diff --git a/src/core/hle/service/filesystem/fsp_pr.h b/src/core/hle/service/filesystem/fsp/fsp_pr.h index bd4e0a730..bd4e0a730 100644 --- a/src/core/hle/service/filesystem/fsp_pr.h +++ b/src/core/hle/service/filesystem/fsp/fsp_pr.h diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp/fsp_srv.cpp index a2397bec4..2be72b021 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp/fsp_srv.cpp @@ -15,18 +15,20 @@  #include "common/settings.h"  #include "common/string_util.h"  #include "core/core.h" -#include "core/file_sys/directory.h"  #include "core/file_sys/errors.h" -#include "core/file_sys/mode.h" +#include "core/file_sys/fs_directory.h" +#include "core/file_sys/fs_filesystem.h"  #include "core/file_sys/nca_metadata.h"  #include "core/file_sys/patch_manager.h"  #include "core/file_sys/romfs_factory.h"  #include "core/file_sys/savedata_factory.h"  #include "core/file_sys/system_archive/system_archive.h" -#include "core/file_sys/vfs.h" +#include "core/file_sys/vfs/vfs.h"  #include "core/hle/result.h"  #include "core/hle/service/filesystem/filesystem.h" -#include "core/hle/service/filesystem/fsp_srv.h" +#include "core/hle/service/filesystem/fsp/fs_i_filesystem.h" +#include "core/hle/service/filesystem/fsp/fs_i_storage.h" +#include "core/hle/service/filesystem/fsp/fsp_srv.h"  #include "core/hle/service/filesystem/romfs_controller.h"  #include "core/hle/service/filesystem/save_data_controller.h"  #include "core/hle/service/hle_ipc.h" @@ -34,19 +36,6 @@  #include "core/reporter.h"  namespace Service::FileSystem { - -struct SizeGetter { -    std::function<u64()> get_free_size; -    std::function<u64()> get_total_size; - -    static SizeGetter FromStorageId(const FileSystemController& fsc, FileSys::StorageId id) { -        return { -            [&fsc, id] { return fsc.GetFreeSpaceSize(id); }, -            [&fsc, id] { return fsc.GetTotalSpaceSize(id); }, -        }; -    } -}; -  enum class FileSystemType : u8 {      Invalid0 = 0,      Invalid1 = 1, @@ -58,525 +47,6 @@ enum class FileSystemType : u8 {      ApplicationPackage = 7,  }; -class IStorage final : public ServiceFramework<IStorage> { -public: -    explicit IStorage(Core::System& system_, FileSys::VirtualFile backend_) -        : ServiceFramework{system_, "IStorage"}, backend(std::move(backend_)) { -        static const FunctionInfo functions[] = { -            {0, &IStorage::Read, "Read"}, -            {1, nullptr, "Write"}, -            {2, nullptr, "Flush"}, -            {3, nullptr, "SetSize"}, -            {4, &IStorage::GetSize, "GetSize"}, -            {5, nullptr, "OperateRange"}, -        }; -        RegisterHandlers(functions); -    } - -private: -    FileSys::VirtualFile backend; - -    void Read(HLERequestContext& ctx) { -        IPC::RequestParser rp{ctx}; -        const s64 offset = rp.Pop<s64>(); -        const s64 length = rp.Pop<s64>(); - -        LOG_DEBUG(Service_FS, "called, offset=0x{:X}, length={}", offset, length); - -        // Error checking -        if (length < 0) { -            LOG_ERROR(Service_FS, "Length is less than 0, length={}", length); -            IPC::ResponseBuilder rb{ctx, 2}; -            rb.Push(FileSys::ERROR_INVALID_SIZE); -            return; -        } -        if (offset < 0) { -            LOG_ERROR(Service_FS, "Offset is less than 0, offset={}", offset); -            IPC::ResponseBuilder rb{ctx, 2}; -            rb.Push(FileSys::ERROR_INVALID_OFFSET); -            return; -        } - -        // Read the data from the Storage backend -        std::vector<u8> output = backend->ReadBytes(length, offset); -        // Write the data to memory -        ctx.WriteBuffer(output); - -        IPC::ResponseBuilder rb{ctx, 2}; -        rb.Push(ResultSuccess); -    } - -    void GetSize(HLERequestContext& ctx) { -        const u64 size = backend->GetSize(); -        LOG_DEBUG(Service_FS, "called, size={}", size); - -        IPC::ResponseBuilder rb{ctx, 4}; -        rb.Push(ResultSuccess); -        rb.Push<u64>(size); -    } -}; - -class IFile final : public ServiceFramework<IFile> { -public: -    explicit IFile(Core::System& system_, FileSys::VirtualFile backend_) -        : ServiceFramework{system_, "IFile"}, backend(std::move(backend_)) { -        static const FunctionInfo functions[] = { -            {0, &IFile::Read, "Read"}, -            {1, &IFile::Write, "Write"}, -            {2, &IFile::Flush, "Flush"}, -            {3, &IFile::SetSize, "SetSize"}, -            {4, &IFile::GetSize, "GetSize"}, -            {5, nullptr, "OperateRange"}, -            {6, nullptr, "OperateRangeWithBuffer"}, -        }; -        RegisterHandlers(functions); -    } - -private: -    FileSys::VirtualFile backend; - -    void Read(HLERequestContext& ctx) { -        IPC::RequestParser rp{ctx}; -        const u64 option = rp.Pop<u64>(); -        const s64 offset = rp.Pop<s64>(); -        const s64 length = rp.Pop<s64>(); - -        LOG_DEBUG(Service_FS, "called, option={}, offset=0x{:X}, length={}", option, offset, -                  length); - -        // Error checking -        if (length < 0) { -            LOG_ERROR(Service_FS, "Length is less than 0, length={}", length); -            IPC::ResponseBuilder rb{ctx, 2}; -            rb.Push(FileSys::ERROR_INVALID_SIZE); -            return; -        } -        if (offset < 0) { -            LOG_ERROR(Service_FS, "Offset is less than 0, offset={}", offset); -            IPC::ResponseBuilder rb{ctx, 2}; -            rb.Push(FileSys::ERROR_INVALID_OFFSET); -            return; -        } - -        // Read the data from the Storage backend -        std::vector<u8> output = backend->ReadBytes(length, offset); - -        // Write the data to memory -        ctx.WriteBuffer(output); - -        IPC::ResponseBuilder rb{ctx, 4}; -        rb.Push(ResultSuccess); -        rb.Push(static_cast<u64>(output.size())); -    } - -    void Write(HLERequestContext& ctx) { -        IPC::RequestParser rp{ctx}; -        const u64 option = rp.Pop<u64>(); -        const s64 offset = rp.Pop<s64>(); -        const s64 length = rp.Pop<s64>(); - -        LOG_DEBUG(Service_FS, "called, option={}, offset=0x{:X}, length={}", option, offset, -                  length); - -        // Error checking -        if (length < 0) { -            LOG_ERROR(Service_FS, "Length is less than 0, length={}", length); -            IPC::ResponseBuilder rb{ctx, 2}; -            rb.Push(FileSys::ERROR_INVALID_SIZE); -            return; -        } -        if (offset < 0) { -            LOG_ERROR(Service_FS, "Offset is less than 0, offset={}", offset); -            IPC::ResponseBuilder rb{ctx, 2}; -            rb.Push(FileSys::ERROR_INVALID_OFFSET); -            return; -        } - -        const auto data = ctx.ReadBuffer(); - -        ASSERT_MSG( -            static_cast<s64>(data.size()) <= length, -            "Attempting to write more data than requested (requested={:016X}, actual={:016X}).", -            length, data.size()); - -        // Write the data to the Storage backend -        const auto write_size = -            static_cast<std::size_t>(std::distance(data.begin(), data.begin() + length)); -        const std::size_t written = backend->Write(data.data(), write_size, offset); - -        ASSERT_MSG(static_cast<s64>(written) == length, -                   "Could not write all bytes to file (requested={:016X}, actual={:016X}).", length, -                   written); - -        IPC::ResponseBuilder rb{ctx, 2}; -        rb.Push(ResultSuccess); -    } - -    void Flush(HLERequestContext& ctx) { -        LOG_DEBUG(Service_FS, "called"); - -        // Exists for SDK compatibiltity -- No need to flush file. - -        IPC::ResponseBuilder rb{ctx, 2}; -        rb.Push(ResultSuccess); -    } - -    void SetSize(HLERequestContext& ctx) { -        IPC::RequestParser rp{ctx}; -        const u64 size = rp.Pop<u64>(); -        LOG_DEBUG(Service_FS, "called, size={}", size); - -        backend->Resize(size); - -        IPC::ResponseBuilder rb{ctx, 2}; -        rb.Push(ResultSuccess); -    } - -    void GetSize(HLERequestContext& ctx) { -        const u64 size = backend->GetSize(); -        LOG_DEBUG(Service_FS, "called, size={}", size); - -        IPC::ResponseBuilder rb{ctx, 4}; -        rb.Push(ResultSuccess); -        rb.Push<u64>(size); -    } -}; - -template <typename T> -static void BuildEntryIndex(std::vector<FileSys::Entry>& entries, const std::vector<T>& new_data, -                            FileSys::EntryType type) { -    entries.reserve(entries.size() + new_data.size()); - -    for (const auto& new_entry : new_data) { -        auto name = new_entry->GetName(); - -        if (type == FileSys::EntryType::File && name == FileSys::GetSaveDataSizeFileName()) { -            continue; -        } - -        entries.emplace_back(name, type, -                             type == FileSys::EntryType::Directory ? 0 : new_entry->GetSize()); -    } -} - -class IDirectory final : public ServiceFramework<IDirectory> { -public: -    explicit IDirectory(Core::System& system_, FileSys::VirtualDir backend_, OpenDirectoryMode mode) -        : ServiceFramework{system_, "IDirectory"}, backend(std::move(backend_)) { -        static const FunctionInfo functions[] = { -            {0, &IDirectory::Read, "Read"}, -            {1, &IDirectory::GetEntryCount, "GetEntryCount"}, -        }; -        RegisterHandlers(functions); - -        // TODO(DarkLordZach): Verify that this is the correct behavior. -        // Build entry index now to save time later. -        if (True(mode & OpenDirectoryMode::Directory)) { -            BuildEntryIndex(entries, backend->GetSubdirectories(), FileSys::EntryType::Directory); -        } -        if (True(mode & OpenDirectoryMode::File)) { -            BuildEntryIndex(entries, backend->GetFiles(), FileSys::EntryType::File); -        } -    } - -private: -    FileSys::VirtualDir backend; -    std::vector<FileSys::Entry> entries; -    u64 next_entry_index = 0; - -    void Read(HLERequestContext& ctx) { -        LOG_DEBUG(Service_FS, "called."); - -        // Calculate how many entries we can fit in the output buffer -        const u64 count_entries = ctx.GetWriteBufferNumElements<FileSys::Entry>(); - -        // Cap at total number of entries. -        const u64 actual_entries = std::min(count_entries, entries.size() - next_entry_index); - -        // Determine data start and end -        const auto* begin = reinterpret_cast<u8*>(entries.data() + next_entry_index); -        const auto* end = reinterpret_cast<u8*>(entries.data() + next_entry_index + actual_entries); -        const auto range_size = static_cast<std::size_t>(std::distance(begin, end)); - -        next_entry_index += actual_entries; - -        // Write the data to memory -        ctx.WriteBuffer(begin, range_size); - -        IPC::ResponseBuilder rb{ctx, 4}; -        rb.Push(ResultSuccess); -        rb.Push(actual_entries); -    } - -    void GetEntryCount(HLERequestContext& ctx) { -        LOG_DEBUG(Service_FS, "called"); - -        u64 count = entries.size() - next_entry_index; - -        IPC::ResponseBuilder rb{ctx, 4}; -        rb.Push(ResultSuccess); -        rb.Push(count); -    } -}; - -class IFileSystem final : public ServiceFramework<IFileSystem> { -public: -    explicit IFileSystem(Core::System& system_, FileSys::VirtualDir backend_, SizeGetter size_) -        : ServiceFramework{system_, "IFileSystem"}, backend{std::move(backend_)}, size{std::move( -                                                                                      size_)} { -        static const FunctionInfo functions[] = { -            {0, &IFileSystem::CreateFile, "CreateFile"}, -            {1, &IFileSystem::DeleteFile, "DeleteFile"}, -            {2, &IFileSystem::CreateDirectory, "CreateDirectory"}, -            {3, &IFileSystem::DeleteDirectory, "DeleteDirectory"}, -            {4, &IFileSystem::DeleteDirectoryRecursively, "DeleteDirectoryRecursively"}, -            {5, &IFileSystem::RenameFile, "RenameFile"}, -            {6, nullptr, "RenameDirectory"}, -            {7, &IFileSystem::GetEntryType, "GetEntryType"}, -            {8, &IFileSystem::OpenFile, "OpenFile"}, -            {9, &IFileSystem::OpenDirectory, "OpenDirectory"}, -            {10, &IFileSystem::Commit, "Commit"}, -            {11, &IFileSystem::GetFreeSpaceSize, "GetFreeSpaceSize"}, -            {12, &IFileSystem::GetTotalSpaceSize, "GetTotalSpaceSize"}, -            {13, &IFileSystem::CleanDirectoryRecursively, "CleanDirectoryRecursively"}, -            {14, &IFileSystem::GetFileTimeStampRaw, "GetFileTimeStampRaw"}, -            {15, nullptr, "QueryEntry"}, -            {16, &IFileSystem::GetFileSystemAttribute, "GetFileSystemAttribute"}, -        }; -        RegisterHandlers(functions); -    } - -    void CreateFile(HLERequestContext& ctx) { -        IPC::RequestParser rp{ctx}; - -        const auto file_buffer = ctx.ReadBuffer(); -        const std::string name = Common::StringFromBuffer(file_buffer); - -        const u64 file_mode = rp.Pop<u64>(); -        const u32 file_size = rp.Pop<u32>(); - -        LOG_DEBUG(Service_FS, "called. file={}, mode=0x{:X}, size=0x{:08X}", name, file_mode, -                  file_size); - -        IPC::ResponseBuilder rb{ctx, 2}; -        rb.Push(backend.CreateFile(name, file_size)); -    } - -    void DeleteFile(HLERequestContext& ctx) { -        const auto file_buffer = ctx.ReadBuffer(); -        const std::string name = Common::StringFromBuffer(file_buffer); - -        LOG_DEBUG(Service_FS, "called. file={}", name); - -        IPC::ResponseBuilder rb{ctx, 2}; -        rb.Push(backend.DeleteFile(name)); -    } - -    void CreateDirectory(HLERequestContext& ctx) { -        const auto file_buffer = ctx.ReadBuffer(); -        const std::string name = Common::StringFromBuffer(file_buffer); - -        LOG_DEBUG(Service_FS, "called. directory={}", name); - -        IPC::ResponseBuilder rb{ctx, 2}; -        rb.Push(backend.CreateDirectory(name)); -    } - -    void DeleteDirectory(HLERequestContext& ctx) { -        const auto file_buffer = ctx.ReadBuffer(); -        const std::string name = Common::StringFromBuffer(file_buffer); - -        LOG_DEBUG(Service_FS, "called. directory={}", name); - -        IPC::ResponseBuilder rb{ctx, 2}; -        rb.Push(backend.DeleteDirectory(name)); -    } - -    void DeleteDirectoryRecursively(HLERequestContext& ctx) { -        const auto file_buffer = ctx.ReadBuffer(); -        const std::string name = Common::StringFromBuffer(file_buffer); - -        LOG_DEBUG(Service_FS, "called. directory={}", name); - -        IPC::ResponseBuilder rb{ctx, 2}; -        rb.Push(backend.DeleteDirectoryRecursively(name)); -    } - -    void CleanDirectoryRecursively(HLERequestContext& ctx) { -        const auto file_buffer = ctx.ReadBuffer(); -        const std::string name = Common::StringFromBuffer(file_buffer); - -        LOG_DEBUG(Service_FS, "called. Directory: {}", name); - -        IPC::ResponseBuilder rb{ctx, 2}; -        rb.Push(backend.CleanDirectoryRecursively(name)); -    } - -    void RenameFile(HLERequestContext& ctx) { -        const std::string src_name = Common::StringFromBuffer(ctx.ReadBuffer(0)); -        const std::string dst_name = Common::StringFromBuffer(ctx.ReadBuffer(1)); - -        LOG_DEBUG(Service_FS, "called. file '{}' to file '{}'", src_name, dst_name); - -        IPC::ResponseBuilder rb{ctx, 2}; -        rb.Push(backend.RenameFile(src_name, dst_name)); -    } - -    void OpenFile(HLERequestContext& ctx) { -        IPC::RequestParser rp{ctx}; - -        const auto file_buffer = ctx.ReadBuffer(); -        const std::string name = Common::StringFromBuffer(file_buffer); - -        const auto mode = static_cast<FileSys::Mode>(rp.Pop<u32>()); - -        LOG_DEBUG(Service_FS, "called. file={}, mode={}", name, mode); - -        FileSys::VirtualFile vfs_file{}; -        auto result = backend.OpenFile(&vfs_file, name, mode); -        if (result != ResultSuccess) { -            IPC::ResponseBuilder rb{ctx, 2}; -            rb.Push(result); -            return; -        } - -        auto file = std::make_shared<IFile>(system, vfs_file); - -        IPC::ResponseBuilder rb{ctx, 2, 0, 1}; -        rb.Push(ResultSuccess); -        rb.PushIpcInterface<IFile>(std::move(file)); -    } - -    void OpenDirectory(HLERequestContext& ctx) { -        IPC::RequestParser rp{ctx}; - -        const auto file_buffer = ctx.ReadBuffer(); -        const std::string name = Common::StringFromBuffer(file_buffer); -        const auto mode = rp.PopRaw<OpenDirectoryMode>(); - -        LOG_DEBUG(Service_FS, "called. directory={}, mode={}", name, mode); - -        FileSys::VirtualDir vfs_dir{}; -        auto result = backend.OpenDirectory(&vfs_dir, name); -        if (result != ResultSuccess) { -            IPC::ResponseBuilder rb{ctx, 2}; -            rb.Push(result); -            return; -        } - -        auto directory = std::make_shared<IDirectory>(system, vfs_dir, mode); - -        IPC::ResponseBuilder rb{ctx, 2, 0, 1}; -        rb.Push(ResultSuccess); -        rb.PushIpcInterface<IDirectory>(std::move(directory)); -    } - -    void GetEntryType(HLERequestContext& ctx) { -        const auto file_buffer = ctx.ReadBuffer(); -        const std::string name = Common::StringFromBuffer(file_buffer); - -        LOG_DEBUG(Service_FS, "called. file={}", name); - -        FileSys::EntryType vfs_entry_type{}; -        auto result = backend.GetEntryType(&vfs_entry_type, name); -        if (result != ResultSuccess) { -            IPC::ResponseBuilder rb{ctx, 2}; -            rb.Push(result); -            return; -        } - -        IPC::ResponseBuilder rb{ctx, 3}; -        rb.Push(ResultSuccess); -        rb.Push<u32>(static_cast<u32>(vfs_entry_type)); -    } - -    void Commit(HLERequestContext& ctx) { -        LOG_WARNING(Service_FS, "(STUBBED) called"); - -        IPC::ResponseBuilder rb{ctx, 2}; -        rb.Push(ResultSuccess); -    } - -    void GetFreeSpaceSize(HLERequestContext& ctx) { -        LOG_DEBUG(Service_FS, "called"); - -        IPC::ResponseBuilder rb{ctx, 4}; -        rb.Push(ResultSuccess); -        rb.Push(size.get_free_size()); -    } - -    void GetTotalSpaceSize(HLERequestContext& ctx) { -        LOG_DEBUG(Service_FS, "called"); - -        IPC::ResponseBuilder rb{ctx, 4}; -        rb.Push(ResultSuccess); -        rb.Push(size.get_total_size()); -    } - -    void GetFileTimeStampRaw(HLERequestContext& ctx) { -        const auto file_buffer = ctx.ReadBuffer(); -        const std::string name = Common::StringFromBuffer(file_buffer); - -        LOG_WARNING(Service_FS, "(Partial Implementation) called. file={}", name); - -        FileSys::FileTimeStampRaw vfs_timestamp{}; -        auto result = backend.GetFileTimeStampRaw(&vfs_timestamp, name); -        if (result != ResultSuccess) { -            IPC::ResponseBuilder rb{ctx, 2}; -            rb.Push(result); -            return; -        } - -        IPC::ResponseBuilder rb{ctx, 10}; -        rb.Push(ResultSuccess); -        rb.PushRaw(vfs_timestamp); -    } - -    void GetFileSystemAttribute(HLERequestContext& ctx) { -        LOG_WARNING(Service_FS, "(STUBBED) called"); - -        struct FileSystemAttribute { -            u8 dir_entry_name_length_max_defined; -            u8 file_entry_name_length_max_defined; -            u8 dir_path_name_length_max_defined; -            u8 file_path_name_length_max_defined; -            INSERT_PADDING_BYTES_NOINIT(0x5); -            u8 utf16_dir_entry_name_length_max_defined; -            u8 utf16_file_entry_name_length_max_defined; -            u8 utf16_dir_path_name_length_max_defined; -            u8 utf16_file_path_name_length_max_defined; -            INSERT_PADDING_BYTES_NOINIT(0x18); -            s32 dir_entry_name_length_max; -            s32 file_entry_name_length_max; -            s32 dir_path_name_length_max; -            s32 file_path_name_length_max; -            INSERT_PADDING_WORDS_NOINIT(0x5); -            s32 utf16_dir_entry_name_length_max; -            s32 utf16_file_entry_name_length_max; -            s32 utf16_dir_path_name_length_max; -            s32 utf16_file_path_name_length_max; -            INSERT_PADDING_WORDS_NOINIT(0x18); -            INSERT_PADDING_WORDS_NOINIT(0x1); -        }; -        static_assert(sizeof(FileSystemAttribute) == 0xc0, -                      "FileSystemAttribute has incorrect size"); - -        FileSystemAttribute savedata_attribute{}; -        savedata_attribute.dir_entry_name_length_max_defined = true; -        savedata_attribute.file_entry_name_length_max_defined = true; -        savedata_attribute.dir_entry_name_length_max = 0x40; -        savedata_attribute.file_entry_name_length_max = 0x40; - -        IPC::ResponseBuilder rb{ctx, 50}; -        rb.Push(ResultSuccess); -        rb.PushRaw(savedata_attribute); -    } - -private: -    VfsDirectoryServiceWrapper backend; -    SizeGetter size; -}; -  class ISaveDataInfoReader final : public ServiceFramework<ISaveDataInfoReader> {  public:      explicit ISaveDataInfoReader(Core::System& system_, @@ -960,7 +430,7 @@ void FSP_SRV::OpenSaveDataFileSystem(HLERequestContext& ctx) {          save_data_controller->OpenSaveData(&dir, parameters.space_id, parameters.attribute);      if (result != ResultSuccess) {          IPC::ResponseBuilder rb{ctx, 2, 0, 0}; -        rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND); +        rb.Push(FileSys::ResultTargetNotFound);          return;      } @@ -1127,7 +597,7 @@ void FSP_SRV::OpenPatchDataStorageByCurrentProcess(HLERequestContext& ctx) {      LOG_DEBUG(Service_FS, "called with storage_id={:02X}, title_id={:016X}", storage_id, title_id);      IPC::ResponseBuilder rb{ctx, 2}; -    rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND); +    rb.Push(FileSys::ResultTargetNotFound);  }  void FSP_SRV::OpenDataStorageWithProgramIndex(HLERequestContext& ctx) { diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp/fsp_srv.h index 26980af99..26980af99 100644 --- a/src/core/hle/service/filesystem/fsp_srv.h +++ b/src/core/hle/service/filesystem/fsp/fsp_srv.h diff --git a/src/core/hle/service/filesystem/fsp/fsp_util.h b/src/core/hle/service/filesystem/fsp/fsp_util.h new file mode 100644 index 000000000..253f866db --- /dev/null +++ b/src/core/hle/service/filesystem/fsp/fsp_util.h @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/service/filesystem/filesystem.h" + +namespace Service::FileSystem { + +struct SizeGetter { +    std::function<u64()> get_free_size; +    std::function<u64()> get_total_size; + +    static SizeGetter FromStorageId(const FileSystemController& fsc, FileSys::StorageId id) { +        return { +            [&fsc, id] { return fsc.GetFreeSpaceSize(id); }, +            [&fsc, id] { return fsc.GetTotalSpaceSize(id); }, +        }; +    } +}; + +} // namespace Service::FileSystem diff --git a/src/core/hle/service/filesystem/romfs_controller.h b/src/core/hle/service/filesystem/romfs_controller.h index 9a478f71d..3c3ead344 100644 --- a/src/core/hle/service/filesystem/romfs_controller.h +++ b/src/core/hle/service/filesystem/romfs_controller.h @@ -5,7 +5,7 @@  #include "core/file_sys/nca_metadata.h"  #include "core/file_sys/romfs_factory.h" -#include "core/file_sys/vfs_types.h" +#include "core/file_sys/vfs/vfs_types.h"  namespace Service::FileSystem { diff --git a/src/core/hle/service/filesystem/save_data_controller.cpp b/src/core/hle/service/filesystem/save_data_controller.cpp index d19b3ea1e..03e45f7f9 100644 --- a/src/core/hle/service/filesystem/save_data_controller.cpp +++ b/src/core/hle/service/filesystem/save_data_controller.cpp @@ -44,7 +44,7 @@ Result SaveDataController::CreateSaveData(FileSys::VirtualDir* out_save_data,      auto save_data = factory->Create(space, attribute);      if (save_data == nullptr) { -        return FileSys::ERROR_ENTITY_NOT_FOUND; +        return FileSys::ResultTargetNotFound;      }      *out_save_data = save_data; @@ -56,7 +56,7 @@ Result SaveDataController::OpenSaveData(FileSys::VirtualDir* out_save_data,                                          const FileSys::SaveDataAttribute& attribute) {      auto save_data = factory->Open(space, attribute);      if (save_data == nullptr) { -        return FileSys::ERROR_ENTITY_NOT_FOUND; +        return FileSys::ResultTargetNotFound;      }      *out_save_data = save_data; @@ -67,7 +67,7 @@ Result SaveDataController::OpenSaveDataSpace(FileSys::VirtualDir* out_save_data_                                               FileSys::SaveDataSpaceId space) {      auto save_data_space = factory->GetSaveDataSpaceDirectory(space);      if (save_data_space == nullptr) { -        return FileSys::ERROR_ENTITY_NOT_FOUND; +        return FileSys::ResultTargetNotFound;      }      *out_save_data_space = save_data_space; diff --git a/src/core/hle/service/filesystem/save_data_controller.h b/src/core/hle/service/filesystem/save_data_controller.h index 863188e4c..dc9d713df 100644 --- a/src/core/hle/service/filesystem/save_data_controller.h +++ b/src/core/hle/service/filesystem/save_data_controller.h @@ -5,7 +5,7 @@  #include "core/file_sys/nca_metadata.h"  #include "core/file_sys/savedata_factory.h" -#include "core/file_sys/vfs_types.h" +#include "core/file_sys/vfs/vfs_types.h"  namespace Service::FileSystem { diff --git a/src/core/hle/service/glue/time/manager.cpp b/src/core/hle/service/glue/time/manager.cpp index 6423e5089..b56762941 100644 --- a/src/core/hle/service/glue/time/manager.cpp +++ b/src/core/hle/service/glue/time/manager.cpp @@ -8,7 +8,7 @@  #include "common/settings.h"  #include "common/time_zone.h" -#include "core/file_sys/vfs.h" +#include "core/file_sys/vfs/vfs.h"  #include "core/hle/kernel/svc.h"  #include "core/hle/service/glue/time/manager.h"  #include "core/hle/service/glue/time/time_zone_binary.h" diff --git a/src/core/hle/service/glue/time/manager.h b/src/core/hle/service/glue/time/manager.h index a46ec6364..1de93f8f9 100644 --- a/src/core/hle/service/glue/time/manager.h +++ b/src/core/hle/service/glue/time/manager.h @@ -7,7 +7,7 @@  #include <string>  #include "common/common_types.h" -#include "core/file_sys/vfs_types.h" +#include "core/file_sys/vfs/vfs_types.h"  #include "core/hle/service/glue/time/file_timestamp_worker.h"  #include "core/hle/service/glue/time/standard_steady_clock_resource.h"  #include "core/hle/service/glue/time/worker.h" diff --git a/src/core/hle/service/glue/time/time_zone_binary.cpp b/src/core/hle/service/glue/time/time_zone_binary.cpp index 67969aa3f..d33f784c0 100644 --- a/src/core/hle/service/glue/time/time_zone_binary.cpp +++ b/src/core/hle/service/glue/time/time_zone_binary.cpp @@ -7,7 +7,7 @@  #include "core/file_sys/registered_cache.h"  #include "core/file_sys/romfs.h"  #include "core/file_sys/system_archive/system_archive.h" -#include "core/file_sys/vfs.h" +#include "core/file_sys/vfs/vfs.h"  #include "core/hle/service/filesystem/filesystem.h"  #include "core/hle/service/glue/time/time_zone_binary.h" diff --git a/src/core/hle/service/nfc/nfc_interface.cpp b/src/core/hle/service/nfc/nfc_interface.cpp index 207ac4efe..3e2c7deab 100644 --- a/src/core/hle/service/nfc/nfc_interface.cpp +++ b/src/core/hle/service/nfc/nfc_interface.cpp @@ -301,7 +301,7 @@ Result NfcInterface::TranslateResultToServiceError(Result result) const {          return result;      } -    if (result.module != ErrorModule::NFC) { +    if (result.GetModule() != ErrorModule::NFC) {          return result;      } diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index a25b79513..2258ee609 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp @@ -6,7 +6,7 @@  #include "core/core.h"  #include "core/file_sys/control_metadata.h"  #include "core/file_sys/patch_manager.h" -#include "core/file_sys/vfs.h" +#include "core/file_sys/vfs/vfs.h"  #include "core/hle/service/filesystem/filesystem.h"  #include "core/hle/service/glue/glue_manager.h"  #include "core/hle/service/ipc_helpers.h" diff --git a/src/core/hle/service/set/system_settings_server.cpp b/src/core/hle/service/set/system_settings_server.cpp index f40a1c8f3..b527c39a9 100644 --- a/src/core/hle/service/set/system_settings_server.cpp +++ b/src/core/hle/service/set/system_settings_server.cpp @@ -67,13 +67,13 @@ Result GetFirmwareVersionImpl(FirmwareVersionFormat& out_firmware, Core::System&      const auto ver_file = romfs->GetFile("file");      if (ver_file == nullptr) {          return early_exit_failure("The system version archive didn't contain the file 'file'.", -                                  FileSys::ERROR_INVALID_ARGUMENT); +                                  FileSys::ResultInvalidArgument);      }      auto data = ver_file->ReadAllBytes();      if (data.size() != sizeof(FirmwareVersionFormat)) {          return early_exit_failure("The system version file 'file' was not the correct size.", -                                  FileSys::ERROR_OUT_OF_BOUNDS); +                                  FileSys::ResultOutOfRange);      }      std::memcpy(&out_firmware, data.data(), sizeof(FirmwareVersionFormat));  | 
