@ -4,6 +4,9 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
# include <string_view>
# include "common/fs/path_util.h"
# include "common/string_util.h"
# include "core/file_sys/fssrv/fssrv_sf_path.h"
# include "core/hle/service/cmif_serialization.h"
@ -13,10 +16,29 @@
namespace Service : : FileSystem {
IFileSystem : : IFileSystem ( Core : : System & system_ , FileSys : : VirtualDir dir_ , SizeGetter size_getter_ )
: ServiceFramework { system_ , " IFileSystem " } , backend { std : : make_unique < FileSys : : Fsa : : IFileSystem > (
dir_ ) } ,
size_getter { std : : move ( size_getter_ ) } {
static std : : string ResolveHomebrewCwdRootAlias ( std : : string path ,
std : : string_view homebrew_initial_cwd ) {
if ( homebrew_initial_cwd . empty ( ) ) {
return path ;
}
const std : : string normalized_path = Common : : FS : : SanitizePath ( path ) ;
if ( normalized_path . empty ( ) | | normalized_path = = " / " | |
normalized_path ! = homebrew_initial_cwd | |
path . size ( ) ! = normalized_path . size ( ) + 2 | |
path . substr ( 0 , normalized_path . size ( ) ) ! = normalized_path | |
path . substr ( normalized_path . size ( ) ) ! = " // " ) {
return path ;
}
return " / " ;
}
IFileSystem : : IFileSystem ( Core : : System & system_ , FileSys : : VirtualDir dir_ , SizeGetter size_getter_ ,
std : : string homebrew_initial_cwd )
: ServiceFramework { system_ , " IFileSystem " } ,
backend { std : : make_unique < FileSys : : Fsa : : IFileSystem > ( dir_ ) } ,
size_getter { std : : move ( size_getter_ ) } , homebrew_initial_cwd { std : : move ( homebrew_initial_cwd ) } {
static const FunctionInfo functions [ ] = {
{ 0 , D < & IFileSystem : : CreateFile > , " CreateFile " } ,
{ 1 , D < & IFileSystem : : DeleteFile > , " DeleteFile " } ,
@ -43,7 +65,8 @@ Result IFileSystem::CreateFile(const InLargeData<FileSys::Sf::Path, BufferAttr_H
s32 option , s64 size ) {
LOG_DEBUG ( Service_FS , " called. file={}, option={:#x}, size={:#08x} " , path - > str , option , size ) ;
R_RETURN ( backend - > CreateFile ( FileSys : : Path ( path - > str ) , size ) ) ;
const auto fs_path = ResolveHomebrewCwdRootAlias ( path - > str , homebrew_initial_cwd ) ;
R_RETURN ( backend - > CreateFile ( FileSys : : Path ( fs_path . c_str ( ) ) , size ) ) ;
}
Result IFileSystem : : DeleteFile ( const InLargeData < FileSys : : Sf : : Path , BufferAttr_HipcPointer > path ) {
@ -94,7 +117,8 @@ Result IFileSystem::OpenFile(OutInterface<IFile> out_interface,
LOG_DEBUG ( Service_FS , " called. file={}, mode={} " , path - > str , mode ) ;
FileSys : : VirtualFile vfs_file { } ;
R_TRY ( backend - > OpenFile ( & vfs_file , FileSys : : Path ( path - > str ) ,
const auto fs_path = ResolveHomebrewCwdRootAlias ( path - > str , homebrew_initial_cwd ) ;
R_TRY ( backend - > OpenFile ( & vfs_file , FileSys : : Path ( fs_path . c_str ( ) ) ,
static_cast < FileSys : : OpenMode > ( mode ) ) ) ;
* out_interface = std : : make_shared < IFile > ( system , vfs_file ) ;
@ -107,7 +131,8 @@ Result IFileSystem::OpenDirectory(OutInterface<IDirectory> out_interface,
LOG_DEBUG ( Service_FS , " called. directory={}, mode={} " , path - > str , mode ) ;
FileSys : : VirtualDir vfs_dir { } ;
R_TRY ( backend - > OpenDirectory ( & vfs_dir , FileSys : : Path ( path - > str ) ,
const auto fs_path = ResolveHomebrewCwdRootAlias ( path - > str , homebrew_initial_cwd ) ;
R_TRY ( backend - > OpenDirectory ( & vfs_dir , FileSys : : Path ( fs_path . c_str ( ) ) ,
static_cast < FileSys : : OpenDirectoryMode > ( mode ) ) ) ;
* out_interface = std : : make_shared < IDirectory > ( system , vfs_dir ,
@ -120,7 +145,8 @@ Result IFileSystem::GetEntryType(
LOG_DEBUG ( Service_FS , " called. file={} " , path - > str ) ;
FileSys : : DirectoryEntryType vfs_entry_type { } ;
R_TRY ( backend - > GetEntryType ( & vfs_entry_type , FileSys : : Path ( path - > str ) ) ) ;
const auto fs_path = ResolveHomebrewCwdRootAlias ( path - > str , homebrew_initial_cwd ) ;
R_TRY ( backend - > GetEntryType ( & vfs_entry_type , FileSys : : Path ( fs_path . c_str ( ) ) ) ) ;
* out_type = static_cast < u32 > ( vfs_entry_type ) ;
R_SUCCEED ( ) ;