diff --git a/src/common/std_filesystem.h b/src/common/std_filesystem.h index 40cdb67a74..299624c5a9 100644 --- a/src/common/std_filesystem.h +++ b/src/common/std_filesystem.h @@ -4,7 +4,7 @@ #pragma once -#if _MSC_VER || (__GNUC__ > 8) +#if _MSC_VER #include namespace filesystem = std::filesystem; #else diff --git a/src/core/file_sys/vfs_offset.cpp b/src/core/file_sys/vfs_offset.cpp index c02a8c00d4..0bb6973fe0 100644 --- a/src/core/file_sys/vfs_offset.cpp +++ b/src/core/file_sys/vfs_offset.cpp @@ -23,7 +23,8 @@ bool OffsetVfsFile::Resize(size_t new_size) { size = new_size; } else { auto res = file->Resize(offset + new_size); - if (!res) return false; + if (!res) + return false; size = new_size; } diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp index c7b351db0e..7c89d6ffea 100644 --- a/src/core/file_sys/vfs_real.cpp +++ b/src/core/file_sys/vfs_real.cpp @@ -69,6 +69,9 @@ bool RealVfsFile::Rename(const std::string& name) { RealVfsDirectory::RealVfsDirectory(const filesystem::path& path_, filesystem::perms perms_) : path(path_), perms(perms_) { path.make_preferred(); + if (!filesystem::exists(path) && + (perms_ & filesystem::perms::owner_write) != filesystem::perms::none) + filesystem::create_directory(path); for (const auto& entry : filesystem::directory_iterator(path)) { if (filesystem::is_directory(entry.path())) subdirectories.emplace_back(std::make_shared(entry.path(), perms)); diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 01a8ebb57d..b42654e1fb 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -5,10 +5,13 @@ #include "boost/container/flat_map.hpp" #include "common/common_paths.h" #include "common/file_util.h" +#include "core/core.h" +#include "core/file_sys/errors.h" #include "core/file_sys/filesystem.h" #include "core/file_sys/vfs.h" #include "core/file_sys/vfs_offset.h" #include "core/file_sys/vfs_real.h" +#include "core/hle/kernel/process.h" #include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/filesystem/fsp_srv.h" @@ -96,7 +99,7 @@ ResultVal VfsDirectoryServiceWrapper::OpenFile(const std::string& path, FileSys::Mode mode) const { auto file = backing->GetFileRelative(filesystem::path(path)); if (file == nullptr) - return ResultCode(-1); + return FileSys::ERROR_FILE_NOT_FOUND; if (mode == FileSys::Mode::Append) return MakeResult( std::make_shared(file, 0, file->GetSize())); @@ -135,22 +138,36 @@ ResultVal VfsDirectoryServiceWrapper::GetEntryType( return ResultCode(-1); } +struct SaveDataDeferredFilesystem : DeferredFilesystem { +protected: + v_dir CreateFilesystem() override { + u64 title_id = Core::CurrentProcess()->program_id; + // TODO(DarkLordZach): Users + u32 user_id = 0; + std::string nand_directory = fmt::format( + "{}save/{:016X}/{:08X}/", FileUtil::GetUserPath(D_NAND_IDX), title_id, user_id); + + auto savedata = + std::make_shared(nand_directory, filesystem::perms::all); + return savedata; + } +}; + /** * Map of registered file systems, identified by type. Once an file system is registered here, it * is never removed until UnregisterFileSystems is called. */ -static boost::container::flat_map filesystem_map; +static boost::container::flat_map> filesystem_map; static v_file filesystem_romfs; -ResultCode RegisterFileSystem(v_dir factory, Type type) { - auto result = filesystem_map.emplace(type, factory); +ResultCode RegisterFileSystem(std::unique_ptr&& factory, Type type) { + auto result = filesystem_map.emplace(type, std::move(factory)); bool inserted = result.second; ASSERT_MSG(inserted, "Tried to register more than one system with same id code"); auto& filesystem = result.first->second; - LOG_DEBUG(Service_FS, "Registered file system {} with id code 0x{:08X}", filesystem->GetName(), - static_cast(type)); + NGLOG_DEBUG(Service_FS, "Registered file system with id code 0x{:08X}", static_cast(type)); return RESULT_SUCCESS; } @@ -173,7 +190,7 @@ ResultVal OpenFileSystem(Type type) { return ResultCode(-1); } - return MakeResult(itr->second); + return MakeResult(itr->second->Get()); } ResultVal OpenRomFS() { @@ -191,7 +208,8 @@ ResultCode FormatFileSystem(Type type) { return ResultCode(-1); } - return itr->second->GetParentDirectory()->DeleteSubdirectory(itr->second->GetName()) + return itr->second->Get()->GetParentDirectory()->DeleteSubdirectory( + itr->second->Get()->GetName()) ? RESULT_SUCCESS : ResultCode(-1); } @@ -199,15 +217,11 @@ ResultCode FormatFileSystem(Type type) { void RegisterFileSystems() { filesystem_map.clear(); - std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); std::string sd_directory = FileUtil::GetUserPath(D_SDMC_IDX); + auto sdcard = std::make_shared(sd_directory, filesystem::perms::all); + RegisterFileSystem(std::make_unique(sdcard), Type::SDMC); - auto savedata = - std::make_unique(nand_directory, filesystem::perms::all); - RegisterFileSystem(std::move(savedata), Type::SaveData); - - auto sdcard = std::make_unique(sd_directory, filesystem::perms::all); - RegisterFileSystem(std::move(sdcard), Type::SDMC); + RegisterFileSystem(std::make_unique(), Type::SaveData); } void InstallInterfaces(SM::ServiceManager& service_manager) { diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index b8cc5cb45b..2df7222509 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h @@ -122,12 +122,33 @@ public: ResultVal GetEntryType(const std::string& path) const; }; +struct DeferredFilesystem { + DeferredFilesystem(){}; + + explicit DeferredFilesystem(v_dir vfs_directory) : fs(vfs_directory) {} + + v_dir Get() { + if (fs == nullptr) + fs = CreateFilesystem(); + + return fs; + } + +protected: + virtual v_dir CreateFilesystem() { + return fs; + } + +private: + v_dir fs; +}; + /** * Registers a FileSystem, instances of which can later be opened using its IdCode. * @param factory FileSystem backend interface to use * @param type Type used to access this type of FileSystem */ -ResultCode RegisterFileSystem(v_dir fs, Type type); +ResultCode RegisterFileSystem(std::unique_ptr&& fs, Type type); ResultCode RegisterRomFS(v_file fs);