diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp index d4a12ed10..99af0ffcc 100644 --- a/src/core/file_sys/archive_romfs.cpp +++ b/src/core/file_sys/archive_romfs.cpp @@ -16,16 +16,15 @@ namespace FileSys { -ArchiveFactory_RomFS::ArchiveFactory_RomFS(const Loader::AppLoader& app_loader) - : romfs_data(std::make_shared>()) { +ArchiveFactory_RomFS::ArchiveFactory_RomFS(const Loader::AppLoader& app_loader) { // Load the RomFS from the app - if (Loader::ResultStatus::Success != app_loader.ReadRomFS(*romfs_data)) { + if (Loader::ResultStatus::Success != app_loader.ReadRomFS (m_romfs_file, m_offset, m_size)) { LOG_ERROR(Service_FS, "Unable to read RomFS!"); } } ResultVal> ArchiveFactory_RomFS::Open(const Path& path) { - auto archive = Common::make_unique(romfs_data); + auto archive = Common::make_unique(m_romfs_file, m_offset, m_size); return MakeResult>(std::move(archive)); } diff --git a/src/core/file_sys/archive_romfs.h b/src/core/file_sys/archive_romfs.h index 409bc670a..ea6490330 100644 --- a/src/core/file_sys/archive_romfs.h +++ b/src/core/file_sys/archive_romfs.h @@ -27,7 +27,9 @@ public: ResultCode Format(const Path& path) override; private: - std::shared_ptr> romfs_data; + std::shared_ptr m_romfs_file; + u64 m_offset; + u64 m_size; }; } // namespace FileSys diff --git a/src/core/file_sys/archive_savedatacheck.cpp b/src/core/file_sys/archive_savedatacheck.cpp index e7e4fbf1d..00cd1bfad 100644 --- a/src/core/file_sys/archive_savedatacheck.cpp +++ b/src/core/file_sys/archive_savedatacheck.cpp @@ -31,17 +31,14 @@ ResultVal> ArchiveFactory_SaveDataCheck::Open(co auto vec = path.AsBinary(); const u32* data = reinterpret_cast(vec.data()); std::string file_path = GetSaveDataCheckPath(mount_point, data[1], data[0]); - FileUtil::IOFile file(file_path, "rb"); + auto file = std::make_shared(file_path, "rb"); - if (!file.IsOpen()) { + if (!file->IsOpen()) { return ResultCode(-1); // TODO(Subv): Find the right error code } - auto size = file.GetSize(); - auto raw_data = std::make_shared>(size); - file.ReadBytes(raw_data->data(), size); - file.Close(); + auto size = file->GetSize(); - auto archive = Common::make_unique(std::move(raw_data)); + auto archive = Common::make_unique(file, 0, size); return MakeResult>(std::move(archive)); } diff --git a/src/core/file_sys/ivfc_archive.cpp b/src/core/file_sys/ivfc_archive.cpp index 2d2509d16..131285bc9 100644 --- a/src/core/file_sys/ivfc_archive.cpp +++ b/src/core/file_sys/ivfc_archive.cpp @@ -16,15 +16,12 @@ namespace FileSys { -IVFCArchive::IVFCArchive(std::shared_ptr> data) : data(data) { -} - std::string IVFCArchive::GetName() const { return "IVFC"; } std::unique_ptr IVFCArchive::OpenFile(const Path& path, const Mode mode) const { - return Common::make_unique(data); + return Common::make_unique(m_romfs_file, m_offset, m_size); } bool IVFCArchive::DeleteFile(const Path& path) const { @@ -66,8 +63,10 @@ std::unique_ptr IVFCArchive::OpenDirectory(const Path& path) c size_t IVFCFile::Read(const u64 offset, const u32 length, u8* buffer) const { LOG_TRACE(Service_FS, "called offset=%llu, length=%d", offset, length); - memcpy(buffer, data->data() + offset, length); - return length; + m_romfs_file->Seek(m_offset + offset, SEEK_SET); + u32 read_length = (u32) std::min((u64) length, m_size - offset); + + return m_romfs_file->ReadBytes(buffer, read_length); } size_t IVFCFile::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { @@ -76,7 +75,7 @@ size_t IVFCFile::Write(const u64 offset, const u32 length, const u32 flush, cons } size_t IVFCFile::GetSize() const { - return sizeof(u8) * data->size(); + return sizeof(u8) * m_size; } bool IVFCFile::SetSize(const u64 size) const { diff --git a/src/core/file_sys/ivfc_archive.h b/src/core/file_sys/ivfc_archive.h index 10415798d..f51766114 100644 --- a/src/core/file_sys/ivfc_archive.h +++ b/src/core/file_sys/ivfc_archive.h @@ -26,7 +26,8 @@ namespace FileSys { */ class IVFCArchive : public ArchiveBackend { public: - IVFCArchive(std::shared_ptr> data); + IVFCArchive(std::shared_ptr romfs_file, u64 offset, u64 size) + : m_romfs_file(romfs_file), m_offset(offset), m_size(size) {} std::string GetName() const override; @@ -40,12 +41,15 @@ public: std::unique_ptr OpenDirectory(const Path& path) const override; protected: - std::shared_ptr> data; + std::shared_ptr m_romfs_file; + u64 m_offset; + u64 m_size; }; class IVFCFile : public FileBackend { public: - IVFCFile(std::shared_ptr> data) : data(data) {} + IVFCFile(std::shared_ptr romfs_file, u64 offset, u64 size) + : m_romfs_file(romfs_file), m_offset(offset), m_size(size) {} bool Open() override { return true; } size_t Read(const u64 offset, const u32 length, u8* buffer) const override; @@ -56,7 +60,9 @@ public: void Flush() const override { } private: - std::shared_ptr> data; + std::shared_ptr m_romfs_file; + u64 m_offset; + u64 m_size; }; class IVFCDirectory : public DirectoryBackend { diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 8b14edf00..7030eb6d2 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -122,7 +122,7 @@ ResultStatus LoadFile(const std::string& filename) { case FileType::CXI: case FileType::CCI: { - AppLoader_NCCH app_loader(std::move(file)); + AppLoader_NCCH app_loader(std::move(file), filename); // Load application and RomFS if (ResultStatus::Success == app_loader.Load()) { diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index 87e16fb98..e439a86e0 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -93,10 +93,13 @@ public: /** * Get the RomFS of the application - * @param buffer Reference to buffer to store data + * Since the RomFS is huge, we return a file reference instead of copying to a buffer + * @param romfs_file The file containing the RomFS + * @param offset The offset the romfs begins on + * @param size The size of the romfs * @return ResultStatus result of function */ - virtual ResultStatus ReadRomFS(std::vector& buffer) const { + virtual ResultStatus ReadRomFS(std::shared_ptr& romfs_file, u64& offset, u64& size) const { return ResultStatus::ErrorNotImplemented; } diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index 08993c4fa..8795b2c3b 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -275,7 +275,7 @@ ResultStatus AppLoader_NCCH::ReadLogo(std::vector& buffer) const { return LoadSectionExeFS("logo", buffer); } -ResultStatus AppLoader_NCCH::ReadRomFS(std::vector& buffer) const { +ResultStatus AppLoader_NCCH::ReadRomFS(std::shared_ptr& romfs_file, u64& offset, u64& size) const { if (!file->IsOpen()) return ResultStatus::Error; @@ -287,12 +287,16 @@ ResultStatus AppLoader_NCCH::ReadRomFS(std::vector& buffer) const { LOG_DEBUG(Loader, "RomFS offset: 0x%08X", romfs_offset); LOG_DEBUG(Loader, "RomFS size: 0x%08X", romfs_size); - buffer.resize(romfs_size); - - file->Seek(romfs_offset, SEEK_SET); - if (file->ReadBytes(&buffer[0], romfs_size) != romfs_size) + if (file->GetSize () < romfs_offset + romfs_size) return ResultStatus::Error; + // We reopen the file, to avoid reuse of the file offset + romfs_file.reset(new FileUtil::IOFile(filepath, "rb")); + offset = romfs_offset; + size = romfs_size; + + if (!romfs_file->IsOpen()) + return ResultStatus::Error; return ResultStatus::Success; } LOG_DEBUG(Loader, "NCCH has no RomFS"); diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h index 29e39d2c0..0fe41390a 100644 --- a/src/core/loader/ncch.h +++ b/src/core/loader/ncch.h @@ -163,7 +163,8 @@ namespace Loader { /// Loads an NCCH file (e.g. from a CCI, or the first NCCH in a CXI) class AppLoader_NCCH final : public AppLoader { public: - AppLoader_NCCH(std::unique_ptr&& file) : AppLoader(std::move(file)) { } + AppLoader_NCCH(std::unique_ptr&& file, std::string filepath) + : AppLoader(std::move(file)), filepath(filepath) { } /** * Returns the type of the file @@ -211,7 +212,7 @@ public: * @param buffer Reference to buffer to store data * @return ResultStatus result of function */ - ResultStatus ReadRomFS(std::vector& buffer) const override; + ResultStatus ReadRomFS(std::shared_ptr& romfs_file, u64& offset, u64& size) const override; private: @@ -244,6 +245,8 @@ private: NCCH_Header ncch_header; ExeFs_Header exefs_header; ExHeader_Header exheader_header; + + std::string filepath; }; } // namespace Loader