// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "common/string_util.h" #include "core/file_sys/fssrv/fssrv_sf_path.h" #include "core/hle/service/cmif_serialization.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" namespace Service::FileSystem { IFileSystem::IFileSystem(Core::System& system_, FileSys::VirtualDir dir_, SizeGetter size_getter_) : ServiceFramework{system_, "IFileSystem"}, backend{std::make_unique( dir_)}, size_getter{std::move(size_getter_)} { static const FunctionInfo functions[] = { {0, D<&IFileSystem::CreateFile>, "CreateFile"}, {1, D<&IFileSystem::DeleteFile>, "DeleteFile"}, {2, D<&IFileSystem::CreateDirectory>, "CreateDirectory"}, {3, D<&IFileSystem::DeleteDirectory>, "DeleteDirectory"}, {4, D<&IFileSystem::DeleteDirectoryRecursively>, "DeleteDirectoryRecursively"}, {5, D<&IFileSystem::RenameFile>, "RenameFile"}, {6, nullptr, "RenameDirectory"}, {7, D<&IFileSystem::GetEntryType>, "GetEntryType"}, {8, D<&IFileSystem::OpenFile>, "OpenFile"}, {9, D<&IFileSystem::OpenDirectory>, "OpenDirectory"}, {10, D<&IFileSystem::Commit>, "Commit"}, {11, D<&IFileSystem::GetFreeSpaceSize>, "GetFreeSpaceSize"}, {12, D<&IFileSystem::GetTotalSpaceSize>, "GetTotalSpaceSize"}, {13, D<&IFileSystem::CleanDirectoryRecursively>, "CleanDirectoryRecursively"}, {14, D<&IFileSystem::GetFileTimeStampRaw>, "GetFileTimeStampRaw"}, {15, nullptr, "QueryEntry"}, {16, D<&IFileSystem::GetFileSystemAttribute>, "GetFileSystemAttribute"}, }; RegisterHandlers(functions); } Result IFileSystem::CreateFile(const InLargeData path, s32 option, s64 size) { LOG_DEBUG(Service_FS, "called. file={}, option=0x{:X}, size=0x{:08X}", path->str, option, size); R_RETURN(backend->CreateFile(FileSys::Path(path->str), size)); } Result IFileSystem::DeleteFile(const InLargeData path) { LOG_DEBUG(Service_FS, "called. file={}", path->str); R_RETURN(backend->DeleteFile(FileSys::Path(path->str))); } Result IFileSystem::CreateDirectory( const InLargeData path) { LOG_DEBUG(Service_FS, "called. directory={}", path->str); R_RETURN(backend->CreateDirectory(FileSys::Path(path->str))); } Result IFileSystem::DeleteDirectory( const InLargeData path) { LOG_DEBUG(Service_FS, "called. directory={}", path->str); R_RETURN(backend->DeleteDirectory(FileSys::Path(path->str))); } Result IFileSystem::DeleteDirectoryRecursively( const InLargeData path) { LOG_DEBUG(Service_FS, "called. directory={}", path->str); R_RETURN(backend->DeleteDirectoryRecursively(FileSys::Path(path->str))); } Result IFileSystem::CleanDirectoryRecursively( const InLargeData path) { LOG_DEBUG(Service_FS, "called. Directory: {}", path->str); R_RETURN(backend->CleanDirectoryRecursively(FileSys::Path(path->str))); } Result IFileSystem::RenameFile( const InLargeData old_path, const InLargeData new_path) { LOG_DEBUG(Service_FS, "called. file '{}' to file '{}'", old_path->str, new_path->str); R_RETURN(backend->RenameFile(FileSys::Path(old_path->str), FileSys::Path(new_path->str))); } Result IFileSystem::OpenFile(OutInterface out_interface, const InLargeData path, u32 mode) { LOG_DEBUG(Service_FS, "called. file={}, mode={}", path->str, mode); FileSys::VirtualFile vfs_file{}; R_TRY(backend->OpenFile(&vfs_file, FileSys::Path(path->str), static_cast(mode))); *out_interface = std::make_shared(system, vfs_file); R_SUCCEED(); } Result IFileSystem::OpenDirectory(OutInterface out_interface, const InLargeData path, u32 mode) { LOG_DEBUG(Service_FS, "called. directory={}, mode={}", path->str, mode); FileSys::VirtualDir vfs_dir{}; R_TRY(backend->OpenDirectory(&vfs_dir, FileSys::Path(path->str), static_cast(mode))); *out_interface = std::make_shared(system, vfs_dir, static_cast(mode)); R_SUCCEED(); } Result IFileSystem::GetEntryType( Out out_type, const InLargeData path) { LOG_DEBUG(Service_FS, "called. file={}", path->str); FileSys::DirectoryEntryType vfs_entry_type{}; R_TRY(backend->GetEntryType(&vfs_entry_type, FileSys::Path(path->str))); *out_type = static_cast(vfs_entry_type); R_SUCCEED(); } Result IFileSystem::Commit() { LOG_WARNING(Service_FS, "(STUBBED) called"); R_SUCCEED(); } Result IFileSystem::GetFreeSpaceSize( Out out_size, const InLargeData path) { LOG_DEBUG(Service_FS, "called"); *out_size = size_getter.get_free_size(); R_SUCCEED(); } Result IFileSystem::GetTotalSpaceSize( Out out_size, const InLargeData path) { LOG_DEBUG(Service_FS, "called"); *out_size = size_getter.get_total_size(); R_SUCCEED(); } Result IFileSystem::GetFileTimeStampRaw( Out out_timestamp, const InLargeData path) { LOG_WARNING(Service_FS, "(Partial Implementation) called. file={}", path->str); FileSys::FileTimeStampRaw vfs_timestamp{}; R_TRY(backend->GetFileTimeStampRaw(&vfs_timestamp, FileSys::Path(path->str))); *out_timestamp = vfs_timestamp; R_SUCCEED(); } Result IFileSystem::GetFileSystemAttribute(Out out_attribute) { LOG_WARNING(Service_FS, "(STUBBED) called"); FileSys::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; *out_attribute = savedata_attribute; R_SUCCEED(); } } // namespace Service::FileSystem