diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/file_sys/mode.h | 6 | ||||
-rw-r--r-- | src/core/file_sys/partition_filesystem.cpp | 6 | ||||
-rw-r--r-- | src/core/file_sys/vfs_real.cpp | 47 | ||||
-rw-r--r-- | src/core/hle/ipc_helpers.h | 34 | ||||
-rw-r--r-- | src/core/hle/kernel/hle_ipc.h | 2 | ||||
-rw-r--r-- | src/core/hle/service/filesystem/filesystem.cpp | 45 |
6 files changed, 84 insertions, 56 deletions
diff --git a/src/core/file_sys/mode.h b/src/core/file_sys/mode.h index b4363152a..c95205668 100644 --- a/src/core/file_sys/mode.h +++ b/src/core/file_sys/mode.h @@ -11,7 +11,13 @@ namespace FileSys { enum class Mode : u32 { Read = 1, Write = 2, + ReadWrite = 3, Append = 4, + WriteAppend = 6, }; +inline u32 operator&(Mode lhs, Mode rhs) { + return static_cast<u32>(lhs) & static_cast<u32>(rhs); +} + } // namespace FileSys diff --git a/src/core/file_sys/partition_filesystem.cpp b/src/core/file_sys/partition_filesystem.cpp index 8d2bd9f6b..521e21078 100644 --- a/src/core/file_sys/partition_filesystem.cpp +++ b/src/core/file_sys/partition_filesystem.cpp @@ -65,8 +65,8 @@ PartitionFilesystem::PartitionFilesystem(std::shared_ptr<VfsFile> file) { std::string name( reinterpret_cast<const char*>(&file_data[strtab_offset + entry.strtab_offset])); - pfs_files.emplace_back( - std::make_shared<OffsetVfsFile>(file, entry.size, content_offset + entry.offset, name)); + pfs_files.emplace_back(std::make_shared<OffsetVfsFile>( + file, entry.size, content_offset + entry.offset, std::move(name))); } status = Loader::ResultStatus::Success; @@ -109,7 +109,7 @@ bool PartitionFilesystem::ReplaceFileWithSubdirectory(VirtualFile file, VirtualD return false; const std::ptrdiff_t offset = std::distance(pfs_files.begin(), iter); - pfs_files[offset] = pfs_files.back(); + pfs_files[offset] = std::move(pfs_files.back()); pfs_files.pop_back(); pfs_dirs.emplace_back(std::move(dir)); diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp index 095fec77e..9ce2e1efa 100644 --- a/src/core/file_sys/vfs_real.cpp +++ b/src/core/file_sys/vfs_real.cpp @@ -13,24 +13,31 @@ namespace FileSys { -static std::string PermissionsToCharArray(Mode perms) { - std::string out; - switch (perms) { - case Mode::Read: - out += "r"; - break; - case Mode::Write: - out += "r+"; - break; - case Mode::Append: - out += "a"; - break; +static std::string ModeFlagsToString(Mode mode) { + std::string mode_str; + + // Calculate the correct open mode for the file. + if (mode & Mode::Read && mode & Mode::Write) { + if (mode & Mode::Append) + mode_str = "a+"; + else + mode_str = "r+"; + } else { + if (mode & Mode::Read) + mode_str = "r"; + else if (mode & Mode::Append) + mode_str = "a"; + else if (mode & Mode::Write) + mode_str = "w"; } - return out + "b"; + + mode_str += "b"; + + return mode_str; } RealVfsFile::RealVfsFile(const std::string& path_, Mode perms_) - : backing(path_, PermissionsToCharArray(perms_).c_str()), path(path_), + : backing(path_, ModeFlagsToString(perms_).c_str()), path(path_), parent_path(FileUtil::GetParentPath(path_)), path_components(FileUtil::SplitPathComponents(path_)), parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)), @@ -53,11 +60,11 @@ std::shared_ptr<VfsDirectory> RealVfsFile::GetContainingDirectory() const { } bool RealVfsFile::IsWritable() const { - return perms == Mode::Append || perms == Mode::Write; + return (perms & Mode::WriteAppend) != 0; } bool RealVfsFile::IsReadable() const { - return perms == Mode::Read || perms == Mode::Write; + return (perms & Mode::ReadWrite) != 0; } size_t RealVfsFile::Read(u8* data, size_t length, size_t offset) const { @@ -79,7 +86,7 @@ bool RealVfsFile::Rename(std::string_view name) { path = (parent_path + DIR_SEP).append(name); path_components = parent_components; path_components.push_back(std::move(name_str)); - backing = FileUtil::IOFile(path, PermissionsToCharArray(perms).c_str()); + backing = FileUtil::IOFile(path, ModeFlagsToString(perms).c_str()); return out; } @@ -93,7 +100,7 @@ RealVfsDirectory::RealVfsDirectory(const std::string& path_, Mode perms_) path_components(FileUtil::SplitPathComponents(path)), parent_components(FileUtil::SliceVector(path_components, 0, path_components.size() - 1)), perms(perms_) { - if (!FileUtil::Exists(path) && (perms == Mode::Write || perms == Mode::Append)) + if (!FileUtil::Exists(path) && perms & Mode::WriteAppend) FileUtil::CreateDir(path); if (perms == Mode::Append) @@ -120,11 +127,11 @@ std::vector<std::shared_ptr<VfsDirectory>> RealVfsDirectory::GetSubdirectories() } bool RealVfsDirectory::IsWritable() const { - return perms == Mode::Write || perms == Mode::Append; + return (perms & Mode::WriteAppend) != 0; } bool RealVfsDirectory::IsReadable() const { - return perms == Mode::Read || perms == Mode::Write; + return (perms & Mode::ReadWrite) != 0; } std::string RealVfsDirectory::GetName() const { diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index 8b5b06f31..f5bd27a75 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h @@ -25,9 +25,9 @@ protected: ptrdiff_t index = 0; public: - RequestHelperBase(u32* command_buffer) : cmdbuf(command_buffer) {} + explicit RequestHelperBase(u32* command_buffer) : cmdbuf(command_buffer) {} - RequestHelperBase(Kernel::HLERequestContext& context) + explicit RequestHelperBase(Kernel::HLERequestContext& context) : context(&context), cmdbuf(context.CommandBuffer()) {} void Skip(unsigned size_in_words, bool set_to_null) { @@ -56,13 +56,6 @@ public: class ResponseBuilder : public RequestHelperBase { public: - ResponseBuilder(u32* command_buffer) : RequestHelperBase(command_buffer) {} - - u32 normal_params_size{}; - u32 num_handles_to_copy{}; - u32 num_objects_to_move{}; ///< Domain objects or move handles, context dependent - std::ptrdiff_t datapayload_index{}; - /// Flags used for customizing the behavior of ResponseBuilder enum class Flags : u32 { None = 0, @@ -71,9 +64,11 @@ public: AlwaysMoveHandles = 1, }; - ResponseBuilder(Kernel::HLERequestContext& context, u32 normal_params_size, - u32 num_handles_to_copy = 0, u32 num_objects_to_move = 0, - Flags flags = Flags::None) + explicit ResponseBuilder(u32* command_buffer) : RequestHelperBase(command_buffer) {} + + explicit ResponseBuilder(Kernel::HLERequestContext& context, u32 normal_params_size, + u32 num_handles_to_copy = 0, u32 num_objects_to_move = 0, + Flags flags = Flags::None) : RequestHelperBase(context), normal_params_size(normal_params_size), num_handles_to_copy(num_handles_to_copy), num_objects_to_move(num_objects_to_move) { @@ -206,6 +201,12 @@ public: template <typename... O> void PushCopyObjects(Kernel::SharedPtr<O>... pointers); + +private: + u32 normal_params_size{}; + u32 num_handles_to_copy{}; + u32 num_objects_to_move{}; ///< Domain objects or move handles, context dependent + std::ptrdiff_t datapayload_index{}; }; /// Push /// @@ -273,9 +274,9 @@ inline void ResponseBuilder::PushMoveObjects(Kernel::SharedPtr<O>... pointers) { class RequestParser : public RequestHelperBase { public: - RequestParser(u32* command_buffer) : RequestHelperBase(command_buffer) {} + explicit RequestParser(u32* command_buffer) : RequestHelperBase(command_buffer) {} - RequestParser(Kernel::HLERequestContext& context) : RequestHelperBase(context) { + explicit RequestParser(Kernel::HLERequestContext& context) : RequestHelperBase(context) { ASSERT_MSG(context.GetDataPayloadOffset(), "context is incomplete"); Skip(context.GetDataPayloadOffset(), false); // Skip the u64 command id, it's already stored in the context @@ -285,8 +286,9 @@ public: ResponseBuilder MakeBuilder(u32 normal_params_size, u32 num_handles_to_copy, u32 num_handles_to_move, - ResponseBuilder::Flags flags = ResponseBuilder::Flags::None) { - return {*context, normal_params_size, num_handles_to_copy, num_handles_to_move, flags}; + ResponseBuilder::Flags flags = ResponseBuilder::Flags::None) const { + return ResponseBuilder{*context, normal_params_size, num_handles_to_copy, + num_handles_to_move, flags}; } template <typename T> diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 01b805df8..84727f748 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -91,7 +91,7 @@ protected: */ class HLERequestContext { public: - HLERequestContext(SharedPtr<Kernel::ServerSession> session); + explicit HLERequestContext(SharedPtr<ServerSession> session); ~HLERequestContext(); /// Returns a pointer to the IPC command buffer for this request. diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index dbfe06cbc..fdd2fda18 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -24,7 +24,8 @@ namespace Service::FileSystem { constexpr u64 EMULATED_SD_REPORTED_SIZE = 32000000000; static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base, - std::string_view dir_name) { + std::string_view dir_name_) { + std::string dir_name(FileUtil::SanitizePath(dir_name_)); if (dir_name.empty() || dir_name == "." || dir_name == "/" || dir_name == "\\") return base; @@ -38,7 +39,8 @@ std::string VfsDirectoryServiceWrapper::GetName() const { return backing->GetName(); } -ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path, u64 size) const { +ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 size) const { + std::string path(FileUtil::SanitizePath(path_)); auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); auto file = dir->CreateFile(FileUtil::GetFilename(path)); if (file == nullptr) { @@ -52,7 +54,8 @@ ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path, u64 s return RESULT_SUCCESS; } -ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path) const { +ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path_) const { + std::string path(FileUtil::SanitizePath(path_)); auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); if (path == "/" || path == "\\") { // TODO(DarkLordZach): Why do games call this and what should it do? Works as is but... @@ -60,14 +63,15 @@ ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path) const } if (dir->GetFile(FileUtil::GetFilename(path)) == nullptr) return FileSys::ERROR_PATH_NOT_FOUND; - if (!backing->DeleteFile(FileUtil::GetFilename(path))) { + if (!dir->DeleteFile(FileUtil::GetFilename(path))) { // TODO(DarkLordZach): Find a better error code for this return ResultCode(-1); } return RESULT_SUCCESS; } -ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path) const { +ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path_) const { + std::string path(FileUtil::SanitizePath(path_)); auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); if (dir == nullptr && FileUtil::GetFilename(FileUtil::GetParentPath(path)).empty()) dir = backing; @@ -79,7 +83,8 @@ ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path) return RESULT_SUCCESS; } -ResultCode VfsDirectoryServiceWrapper::DeleteDirectory(const std::string& path) const { +ResultCode VfsDirectoryServiceWrapper::DeleteDirectory(const std::string& path_) const { + std::string path(FileUtil::SanitizePath(path_)); auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); if (!dir->DeleteSubdirectory(FileUtil::GetFilename(path))) { // TODO(DarkLordZach): Find a better error code for this @@ -88,7 +93,8 @@ ResultCode VfsDirectoryServiceWrapper::DeleteDirectory(const std::string& path) return RESULT_SUCCESS; } -ResultCode VfsDirectoryServiceWrapper::DeleteDirectoryRecursively(const std::string& path) const { +ResultCode VfsDirectoryServiceWrapper::DeleteDirectoryRecursively(const std::string& path_) const { + std::string path(FileUtil::SanitizePath(path_)); auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); if (!dir->DeleteSubdirectoryRecursive(FileUtil::GetFilename(path))) { // TODO(DarkLordZach): Find a better error code for this @@ -97,8 +103,10 @@ ResultCode VfsDirectoryServiceWrapper::DeleteDirectoryRecursively(const std::str return RESULT_SUCCESS; } -ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path, - const std::string& dest_path) const { +ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path_, + const std::string& dest_path_) const { + std::string src_path(FileUtil::SanitizePath(src_path_)); + std::string dest_path(FileUtil::SanitizePath(dest_path_)); auto src = backing->GetFileRelative(src_path); if (FileUtil::GetParentPath(src_path) == FileUtil::GetParentPath(dest_path)) { // Use more-optimized vfs implementation rename. @@ -130,8 +138,10 @@ ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path, return RESULT_SUCCESS; } -ResultCode VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path, - const std::string& dest_path) const { +ResultCode VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path_, + const std::string& dest_path_) const { + std::string src_path(FileUtil::SanitizePath(src_path_)); + std::string dest_path(FileUtil::SanitizePath(dest_path_)); auto src = GetDirectoryRelativeWrapped(backing, src_path); if (FileUtil::GetParentPath(src_path) == FileUtil::GetParentPath(dest_path)) { // Use more-optimized vfs implementation rename. @@ -154,8 +164,9 @@ ResultCode VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_pa return ResultCode(-1); } -ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::string& path, +ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::string& path_, FileSys::Mode mode) const { + std::string path(FileUtil::SanitizePath(path_)); auto npath = path; while (npath.size() > 0 && (npath[0] == '/' || npath[0] == '\\')) npath = npath.substr(1); @@ -171,7 +182,8 @@ ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std:: return MakeResult<FileSys::VirtualFile>(file); } -ResultVal<FileSys::VirtualDir> VfsDirectoryServiceWrapper::OpenDirectory(const std::string& path) { +ResultVal<FileSys::VirtualDir> VfsDirectoryServiceWrapper::OpenDirectory(const std::string& path_) { + std::string path(FileUtil::SanitizePath(path_)); auto dir = GetDirectoryRelativeWrapped(backing, path); if (dir == nullptr) { // TODO(DarkLordZach): Find a better error code for this @@ -188,7 +200,8 @@ u64 VfsDirectoryServiceWrapper::GetFreeSpaceSize() const { } ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType( - const std::string& path) const { + const std::string& path_) const { + std::string path(FileUtil::SanitizePath(path_)); auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); if (dir == nullptr) return FileSys::ERROR_PATH_NOT_FOUND; @@ -272,9 +285,9 @@ void RegisterFileSystems() { sdmc_factory = nullptr; auto nand_directory = std::make_shared<FileSys::RealVfsDirectory>( - FileUtil::GetUserPath(FileUtil::UserPath::NANDDir), FileSys::Mode::Write); + FileUtil::GetUserPath(FileUtil::UserPath::NANDDir), FileSys::Mode::ReadWrite); auto sd_directory = std::make_shared<FileSys::RealVfsDirectory>( - FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir), FileSys::Mode::Write); + FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir), FileSys::Mode::ReadWrite); auto savedata = std::make_unique<FileSys::SaveDataFactory>(std::move(nand_directory)); save_data_factory = std::move(savedata); |