From 8da705d40b8fa6652e0853b83d25ac0e6d8f417b Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Tue, 25 Feb 2020 06:41:47 -0800 Subject: [PATCH] fs.mitm: support html redirection (non-layered, for #814) --- .../ams_mitm/source/amsmitm_fs_utils.cpp | 64 +++++++++---------- .../ams_mitm/source/amsmitm_fs_utils.hpp | 5 ++ .../source/fs_mitm/fs_mitm_service.cpp | 42 ++++++++++-- .../ams_mitm/source/fs_mitm/fsmitm_romfs.cpp | 2 +- 4 files changed, 76 insertions(+), 37 deletions(-) diff --git a/stratosphere/ams_mitm/source/amsmitm_fs_utils.cpp b/stratosphere/ams_mitm/source/amsmitm_fs_utils.cpp index e622610b9..88c372cac 100644 --- a/stratosphere/ams_mitm/source/amsmitm_fs_utils.cpp +++ b/stratosphere/ams_mitm/source/amsmitm_fs_utils.cpp @@ -32,38 +32,6 @@ namespace ams::mitm::fs { return ResultSuccess(); } - void FormatAtmosphereSdPath(char *dst_path, size_t dst_path_size, const char *src_path) { - if (src_path[0] == '/') { - std::snprintf(dst_path, dst_path_size, "/atmosphere%s", src_path); - } else { - std::snprintf(dst_path, dst_path_size, "/atmosphere/%s", src_path); - } - } - - void FormatAtmosphereSdPath(char *dst_path, size_t dst_path_size, const char *subdir, const char *src_path) { - if (src_path[0] == '/') { - std::snprintf(dst_path, dst_path_size, "/atmosphere/%s%s", subdir, src_path); - } else { - std::snprintf(dst_path, dst_path_size, "/atmosphere/%s/%s", subdir, src_path); - } - } - - void FormatAtmosphereSdPath(char *dst_path, size_t dst_path_size, ncm::ProgramId program_id, const char *src_path) { - if (src_path[0] == '/') { - std::snprintf(dst_path, dst_path_size, "/atmosphere/contents/%016lx%s", static_cast(program_id), src_path); - } else { - std::snprintf(dst_path, dst_path_size, "/atmosphere/contents/%016lx/%s", static_cast(program_id), src_path); - } - } - - void FormatAtmosphereSdPath(char *dst_path, size_t dst_path_size, ncm::ProgramId program_id, const char *subdir, const char *src_path) { - if (src_path[0] == '/') { - std::snprintf(dst_path, dst_path_size, "/atmosphere/contents/%016lx/%s%s", static_cast(program_id), subdir, src_path); - } else { - std::snprintf(dst_path, dst_path_size, "/atmosphere/contents/%016lx/%s/%s", static_cast(program_id), subdir, src_path); - } - } - void FormatAtmosphereRomfsPath(char *dst_path, size_t dst_path_size, ncm::ProgramId program_id, const char *src_path) { return FormatAtmosphereSdPath(dst_path, dst_path_size, program_id, "romfs", src_path); } @@ -154,6 +122,38 @@ namespace ams::mitm::fs { return fsFsOpenDirectory(fs, fixed_path, mode, out); } + void FormatAtmosphereSdPath(char *dst_path, size_t dst_path_size, const char *src_path) { + if (src_path[0] == '/') { + std::snprintf(dst_path, dst_path_size, "/atmosphere%s", src_path); + } else { + std::snprintf(dst_path, dst_path_size, "/atmosphere/%s", src_path); + } + } + + void FormatAtmosphereSdPath(char *dst_path, size_t dst_path_size, const char *subdir, const char *src_path) { + if (src_path[0] == '/') { + std::snprintf(dst_path, dst_path_size, "/atmosphere/%s%s", subdir, src_path); + } else { + std::snprintf(dst_path, dst_path_size, "/atmosphere/%s/%s", subdir, src_path); + } + } + + void FormatAtmosphereSdPath(char *dst_path, size_t dst_path_size, ncm::ProgramId program_id, const char *src_path) { + if (src_path[0] == '/') { + std::snprintf(dst_path, dst_path_size, "/atmosphere/contents/%016lx%s", static_cast(program_id), src_path); + } else { + std::snprintf(dst_path, dst_path_size, "/atmosphere/contents/%016lx/%s", static_cast(program_id), src_path); + } + } + + void FormatAtmosphereSdPath(char *dst_path, size_t dst_path_size, ncm::ProgramId program_id, const char *subdir, const char *src_path) { + if (src_path[0] == '/') { + std::snprintf(dst_path, dst_path_size, "/atmosphere/contents/%016lx/%s%s", static_cast(program_id), subdir, src_path); + } else { + std::snprintf(dst_path, dst_path_size, "/atmosphere/contents/%016lx/%s/%s", static_cast(program_id), subdir, src_path); + } + } + /* TODO: Remove this in Atmosphere 0.10.2. */ Result RenameProgramDirectoryForCompatibility(const char *dir_name) { R_TRY(EnsureSdInitialized()); diff --git a/stratosphere/ams_mitm/source/amsmitm_fs_utils.hpp b/stratosphere/ams_mitm/source/amsmitm_fs_utils.hpp index 1be565201..8b4d3f4d4 100644 --- a/stratosphere/ams_mitm/source/amsmitm_fs_utils.hpp +++ b/stratosphere/ams_mitm/source/amsmitm_fs_utils.hpp @@ -38,6 +38,11 @@ namespace ams::mitm::fs { Result OpenAtmosphereSdRomfsDirectory(FsDir *out, ncm::ProgramId program_id, const char *path, u32 mode); Result OpenAtmosphereRomfsDirectory(FsDir *out, ncm::ProgramId program_id, const char *path, u32 mode, FsFileSystem *fs); + void FormatAtmosphereSdPath(char *dst_path, size_t dst_path_size, const char *src_path); + void FormatAtmosphereSdPath(char *dst_path, size_t dst_path_size, const char *subdir, const char *src_path); + void FormatAtmosphereSdPath(char *dst_path, size_t dst_path_size, ncm::ProgramId program_id, const char *src_path); + void FormatAtmosphereSdPath(char *dst_path, size_t dst_path_size, ncm::ProgramId program_id, const char *subdir, const char *src_path); + /* TODO: Remove this in Atmosphere 0.10.2. */ Result RenameProgramDirectoryForCompatibility(const char *dir_name); diff --git a/stratosphere/ams_mitm/source/fs_mitm/fs_mitm_service.cpp b/stratosphere/ams_mitm/source/fs_mitm/fs_mitm_service.cpp index 9b9065e4f..30f3b2aea 100644 --- a/stratosphere/ams_mitm/source/fs_mitm/fs_mitm_service.cpp +++ b/stratosphere/ams_mitm/source/fs_mitm/fs_mitm_service.cpp @@ -27,6 +27,7 @@ namespace ams::mitm::fs { namespace { constexpr const char AtmosphereHblWebContentDir[] = "/atmosphere/hbl_html/"; + constexpr const char ProgramWebContentDir[] = "/manual_html/"; os::Mutex g_data_storage_lock; os::Mutex g_storage_cache_lock; @@ -67,8 +68,6 @@ namespace ams::mitm::fs { Result OpenHblWebContentFileSystem(sf::Out> &out, ncm::ProgramId client_program_id, ncm::ProgramId program_id, FsFileSystemType filesystem_type) { /* Verify eligibility. */ bool is_hbl; - R_UNLESS(ncm::IsWebAppletProgramId(client_program_id), sm::mitm::ResultShouldForwardToSession()); - R_UNLESS(filesystem_type == FsFileSystemType_ContentManual, sm::mitm::ResultShouldForwardToSession()); R_UNLESS(R_SUCCEEDED(pm::info::IsHblProgramId(&is_hbl, program_id)), sm::mitm::ResultShouldForwardToSession()); R_UNLESS(is_hbl, sm::mitm::ResultShouldForwardToSession()); @@ -89,14 +88,49 @@ namespace ams::mitm::fs { return ResultSuccess(); } + Result OpenProgramSpecificWebContentFileSystem(sf::Out> &out, ncm::ProgramId client_program_id, ncm::ProgramId program_id, FsFileSystemType filesystem_type) { + /* Directory must exist. */ + { + FsDir d; + R_UNLESS(R_SUCCEEDED(mitm::fs::OpenAtmosphereSdDirectory(&d, program_id, ProgramWebContentDir, fs::OpenDirectoryMode_Directory)), sm::mitm::ResultShouldForwardToSession()); + fsDirClose(&d); + } + + /* Open the SD card using fs.mitm's session. */ + FsFileSystem sd_fs; + R_TRY(fsOpenSdCardFileSystem(&sd_fs)); + const sf::cmif::DomainObjectId target_object_id{serviceGetObjectId(&sd_fs.s)}; + std::unique_ptr sd_ifs = std::make_unique(sd_fs); + + /* Format the subdirectory path. */ + char program_web_content_path[fs::EntryNameLengthMax + 1]; + FormatAtmosphereSdPath(program_web_content_path, sizeof(program_web_content_path), program_id, ProgramWebContentDir); + + /* Set the output directory. */ + out.SetValue(std::make_shared(std::make_shared(std::move(sd_ifs), program_web_content_path), false), target_object_id); + return ResultSuccess(); + } + + Result OpenWebContentFileSystem(sf::Out> &out, ncm::ProgramId client_program_id, ncm::ProgramId program_id, FsFileSystemType filesystem_type) { + /* Check first that we're a web applet opening web content. */ + R_UNLESS(ncm::IsWebAppletProgramId(client_program_id), sm::mitm::ResultShouldForwardToSession()); + R_UNLESS(filesystem_type == FsFileSystemType_ContentManual, sm::mitm::ResultShouldForwardToSession()); + + /* Try to mount the HBL web filesystem. If this succeeds then we're done. */ + R_UNLESS(R_FAILED(OpenHblWebContentFileSystem(out, client_program_id, program_id, filesystem_type)), ResultSuccess()); + + /* If we're not opening a HBL filesystem, just try to open a generic one. */ + return OpenProgramSpecificWebContentFileSystem(out, client_program_id, program_id, filesystem_type); + } + } Result FsMitmService::OpenFileSystemWithPatch(sf::Out> out, ncm::ProgramId program_id, u32 _filesystem_type) { - return OpenHblWebContentFileSystem(out, this->client_info.program_id, program_id, static_cast(_filesystem_type)); + return OpenWebContentFileSystem(out, this->client_info.program_id, program_id, static_cast(_filesystem_type)); } Result FsMitmService::OpenFileSystemWithId(sf::Out> out, const fssrv::sf::Path &path, ncm::ProgramId program_id, u32 _filesystem_type) { - return OpenHblWebContentFileSystem(out, this->client_info.program_id, program_id, static_cast(_filesystem_type)); + return OpenWebContentFileSystem(out, this->client_info.program_id, program_id, static_cast(_filesystem_type)); } Result FsMitmService::OpenSdCardFileSystem(sf::Out> out) { diff --git a/stratosphere/ams_mitm/source/fs_mitm/fsmitm_romfs.cpp b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_romfs.cpp index efe895e18..b0d037f7a 100644 --- a/stratosphere/ams_mitm/source/fs_mitm/fsmitm_romfs.cpp +++ b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_romfs.cpp @@ -114,7 +114,7 @@ namespace ams::mitm::fs { os::Mutex g_fs_romfs_path_lock; char g_fs_romfs_path_buffer[fs::EntryNameLengthMax + 1]; - __attribute__((noinline)) void OpenFileSystemRomfsDirectory(FsDir *out, ncm::ProgramId program_id, BuildDirectoryContext *parent, fs::OpenDirectoryMode mode, FsFileSystem *fs) { + NOINLINE void OpenFileSystemRomfsDirectory(FsDir *out, ncm::ProgramId program_id, BuildDirectoryContext *parent, fs::OpenDirectoryMode mode, FsFileSystem *fs) { std::scoped_lock lk(g_fs_romfs_path_lock); parent->GetPath(g_fs_romfs_path_buffer); R_ABORT_UNLESS(mitm::fs::OpenAtmosphereRomfsDirectory(out, program_id, g_fs_romfs_path_buffer, mode, fs));