From a95836552e95cdabd67d3a10863d7e9cf9aa63ba Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 28 Jun 2018 20:39:23 -0600 Subject: [PATCH] fs.mitm: Use less path memory, fix source concat. (Fixes BotW, probably others) --- .../fs_mitm/source/fsmitm_romfsbuild.cpp | 59 ++++++++++++++++--- .../fs_mitm/source/fsmitm_romfsbuild.hpp | 6 +- .../fs_mitm/source/fsmitm_service.cpp | 2 +- stratosphere/fs_mitm/source/mitm_session.hpp | 1 - 4 files changed, 55 insertions(+), 13 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp index e9406e123..6fa446fcf 100644 --- a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp @@ -20,25 +20,28 @@ void RomFSBuildContext::VisitDirectory(FsFileSystem *filesys, RomFSBuildDirector if (this->dir_entry.type == ENTRYTYPE_DIR) { RomFSBuildDirectoryContext *child = new RomFSBuildDirectoryContext({0}); /* Set child's path. */ - strcpy(child->path, parent->path); child->cur_path_ofs = parent->path_len + 1; child->path_len = child->cur_path_ofs + strlen(this->dir_entry.name); - if (child->path_len > sizeof(child->path)) { + child->path = new char[child->path_len + 1]; + strcpy(child->path, parent->path); + if (child->path_len > FS_MAX_PATH - 1) { fatalSimple(0xF601); } strcat(child->path + parent->path_len, "/"); strcat(child->path + parent->path_len, this->dir_entry.name); if (!this->AddDirectory(parent, child, NULL)) { + delete child->path; delete child; } } else if (this->dir_entry.type == ENTRYTYPE_FILE) { RomFSBuildFileContext *child = new RomFSBuildFileContext({0}); /* Set child's path. */ - strcpy(child->path, parent->path); child->cur_path_ofs = parent->path_len + 1; child->path_len = child->cur_path_ofs + strlen(this->dir_entry.name); - if (child->path_len > sizeof(child->path)) { + child->path = new char[child->path_len + 1]; + strcpy(child->path, parent->path); + if (child->path_len > FS_MAX_PATH - 1) { fatalSimple(0xF601); } strcat(child->path + parent->path_len, "/"); @@ -49,6 +52,7 @@ void RomFSBuildContext::VisitDirectory(FsFileSystem *filesys, RomFSBuildDirector child->size = this->dir_entry.fileSize; if (!this->AddFile(parent, child)) { + delete child->path; delete child; } } else { @@ -89,10 +93,11 @@ void RomFSBuildContext::VisitDirectory(RomFSBuildDirectoryContext *parent, u32 p while (cur_file != NULL) { RomFSBuildFileContext *child = new RomFSBuildFileContext({0}); /* Set child's path. */ - strcpy(child->path, parent->path); child->cur_path_ofs = parent->path_len + 1; child->path_len = child->cur_path_ofs + cur_file->name_size; - if (child->path_len > sizeof(child->path)) { + child->path = new char[child->path_len + 1]; + strcpy(child->path, parent->path); + if (child->path_len > FS_MAX_PATH - 1) { fatalSimple(0xF601); } strcat(child->path + parent->path_len, "/"); @@ -102,6 +107,7 @@ void RomFSBuildContext::VisitDirectory(RomFSBuildDirectoryContext *parent, u32 p child->source = this->cur_source_type; child->orig_offset = cur_file->offset; if (!this->AddFile(parent, child)) { + delete child->path; delete child; } if (cur_file->sibling == ROMFS_ENTRY_EMPTY) { @@ -117,10 +123,11 @@ void RomFSBuildContext::VisitDirectory(RomFSBuildDirectoryContext *parent, u32 p while (cur_child != NULL) { RomFSBuildDirectoryContext *child = new RomFSBuildDirectoryContext({0}); /* Set child's path. */ - strcpy(child->path, parent->path); child->cur_path_ofs = parent->path_len + 1; child->path_len = child->cur_path_ofs + cur_child->name_size; - if (child->path_len > sizeof(child->path)) { + child->path = new char[child->path_len + 1]; + strcpy(child->path, parent->path); + if (child->path_len > FS_MAX_PATH - 1) { fatalSimple(0xF601); } strcat(child->path + parent->path_len, "/"); @@ -128,6 +135,7 @@ void RomFSBuildContext::VisitDirectory(RomFSBuildDirectoryContext *parent, u32 p RomFSBuildDirectoryContext *real = NULL; if (!this->AddDirectory(parent, child, &real)) { + delete child->path; delete child; } if (real == NULL) { @@ -313,12 +321,25 @@ void RomFSBuildContext::Build(std::vector *out_infos) { /* Determine file offsets. */ cur_file = this->files; entry_offset = 0; + RomFSBuildFileContext *prev_file = NULL; while (cur_file != NULL) { this->file_partition_size = (this->file_partition_size + 0xFULL) & ~0xFULL; + /* Check for extra padding in the original romfs source and preserve it, to help ourselves later. */ + if (prev_file && prev_file->source == cur_file->source && (prev_file->source == RomFSDataSource::BaseRomFS || prev_file->source == RomFSDataSource::FileRomFS)) { + u64 expected = (this->file_partition_size - prev_file->offset + prev_file->orig_offset); + if (expected != cur_file->orig_offset) { + if (expected > cur_file->orig_offset) { + /* This case should NEVER happen. */ + fatalSimple(0xF601); + } + this->file_partition_size += cur_file->orig_offset - expected; + } + } cur_file->offset = this->file_partition_size; this->file_partition_size += cur_file->size; cur_file->entry_offset = entry_offset; entry_offset += sizeof(RomFSFileEntry) + ((cur_file->path_len - cur_file->cur_path_ofs + 3) & ~3); + prev_file = cur_file; cur_file = cur_file->next; } @@ -357,7 +378,7 @@ void RomFSBuildContext::Build(std::vector *out_infos) { case RomFSDataSource::BaseRomFS: case RomFSDataSource::FileRomFS: /* Try to compact, if possible. */ - if (out_infos->back().type == cur_file->source) { + if (out_infos->back().type == cur_file->source && ((out_infos->back().virtual_offset + out_infos->back().size + 0xFULL) & ~0xFULL) == cur_file->offset + ROMFS_FILEPARTITION_OFS) { out_infos->back().size = cur_file->offset + ROMFS_FILEPARTITION_OFS + cur_file->size - out_infos->back().virtual_offset; } else { out_infos->emplace_back(cur_file->offset + ROMFS_FILEPARTITION_OFS, cur_file->size, cur_file->orig_offset + ROMFS_FILEPARTITION_OFS, cur_file->source); @@ -376,6 +397,7 @@ void RomFSBuildContext::Build(std::vector *out_infos) { RomFSBuildFileContext *temp = cur_file; cur_file = cur_file->next; + delete temp->path; delete temp; } @@ -399,6 +421,7 @@ void RomFSBuildContext::Build(std::vector *out_infos) { RomFSBuildDirectoryContext *temp = cur_dir; cur_dir = cur_dir->next; + delete temp->path; delete temp; } @@ -414,5 +437,23 @@ void RomFSBuildContext::Build(std::vector *out_infos) { header->file_hash_table_ofs = header->dir_table_ofs + header->dir_table_size; header->file_table_ofs = header->file_hash_table_ofs + header->file_hash_table_size; + /* For debugging, uncomment this to get a log of the generated metadata tables. */ + /* + { + FsFileSystem sd_fs; + if (R_SUCCEEDED(fsMountSdcard(&sd_fs))) { + FsFile f; + fsFsCreateFile(&sd_fs, "/METADATALOG.bin", this->dir_hash_table_size + this->dir_table_size + this->file_hash_table_size + this->file_table_size + sizeof(*header), 0); + if (R_SUCCEEDED(fsFsOpenFile(&sd_fs, "/METADATALOG.bin", FS_OPEN_READ | FS_OPEN_WRITE, &f))) { + fsFileSetSize(&f, this->dir_hash_table_size + this->dir_table_size + this->file_hash_table_size + this->file_table_size + sizeof(*header)); + fsFileWrite(&f, 0, header, sizeof(*header)); + fsFileWrite(&f, sizeof(*header), metadata, this->dir_hash_table_size + this->dir_table_size + this->file_hash_table_size + this->file_table_size); + fsFileClose(&f); + } + fsFsClose(&sd_fs); + } + } + */ + out_infos->emplace_back(header->dir_hash_table_ofs, this->dir_hash_table_size + this->dir_table_size + this->file_hash_table_size + this->file_table_size, metadata, RomFSDataSource::Memory); } diff --git a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp index 892c2066a..aafd2685a 100644 --- a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp @@ -138,7 +138,7 @@ static_assert(sizeof(RomFSFileEntry) == 0x20, "Incorrect RomFSFileEntry definiti struct RomFSBuildFileContext; struct RomFSBuildDirectoryContext { - char path[FS_MAX_PATH]; + char *path; u32 cur_path_ofs; u32 path_len; u32 entry_offset = 0; @@ -150,7 +150,7 @@ struct RomFSBuildDirectoryContext { }; struct RomFSBuildFileContext { - char path[FS_MAX_PATH]; + char *path; u32 cur_path_ofs; u32 path_len; u32 entry_offset = 0; @@ -187,6 +187,8 @@ class RomFSBuildContext { public: RomFSBuildContext(u64 tid) : title_id(tid), root(NULL), files(NULL), num_dirs(0), num_files(0), dir_table_size(0), file_table_size(0), dir_hash_table_size(0), file_hash_table_size(0), file_partition_size(0) { this->root = new RomFSBuildDirectoryContext({0}); + this->root->path = new char[1]; + this->root->path[0] = '\x00'; this->num_dirs = 1; this->dir_table_size = 0x18; } diff --git a/stratosphere/fs_mitm/source/fsmitm_service.cpp b/stratosphere/fs_mitm/source/fsmitm_service.cpp index f23794039..f3b768626 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.cpp @@ -18,7 +18,7 @@ Result FsMitMService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_i rc = WrapIpcCommandImpl<&FsMitMService::open_data_storage_by_current_process>(this, r, out_c, pointer_buffer, pointer_buffer_size); break; case FspSrvCmd::OpenDataStorageByDataId: - rc = WrapIpcCommandImpl<&FsMitMService::open_data_storage_by_data_id>(this, r, out_c, pointer_buffer, pointer_buffer_size); + //rc = WrapIpcCommandImpl<&FsMitMService::open_data_storage_by_data_id>(this, r, out_c, pointer_buffer, pointer_buffer_size); break; default: break; diff --git a/stratosphere/fs_mitm/source/mitm_session.hpp b/stratosphere/fs_mitm/source/mitm_session.hpp index 1dd801c93..bc4fe0f09 100644 --- a/stratosphere/fs_mitm/source/mitm_session.hpp +++ b/stratosphere/fs_mitm/source/mitm_session.hpp @@ -130,7 +130,6 @@ class MitMSession final : public ISession { MitMSession *new_sess = new MitMSession((MitMServer *)this->server, s_h, c_h, cur_out_r.Handles[0]); new_sess->service_object = this->service_object; - IServiceObject *obj = this->service_object.get(); if (this->is_domain) { new_sess->is_domain = true;