diff --git a/stratosphere/ams_mitm/source/fs_mitm/fs_shim.c b/stratosphere/ams_mitm/source/fs_mitm/fs_shim.c index 915366bb8..2efaddca2 100644 --- a/stratosphere/ams_mitm/source/fs_mitm/fs_shim.c +++ b/stratosphere/ams_mitm/source/fs_mitm/fs_shim.c @@ -132,6 +132,98 @@ Result fsOpenDataStorageByDataIdFwd(Service* s, FsStorageId storage_id, u64 data return rc; } +Result fsOpenFileSystemWithPatchFwd(Service* s, FsFileSystem* out, u64 titleId, FsFileSystemType fsType) { + if (hosversionBefore(2, 0, 0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + } + + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u32 fsType; + u64 titleId; + } *raw; + + raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 7; + raw->fsType = fsType; + raw->titleId = titleId; + + Result rc = serviceIpcDispatch(s); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(s, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + serviceCreateSubservice(&out->s, s, &r, 0); + } + } + + return rc; +} + +Result fsOpenFileSystemWithIdFwd(Service* s, FsFileSystem* out, u64 titleId, FsFileSystemType fsType, const char* contentPath) { + if (hosversionBefore(2, 0, 0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + } + + char sendStr[FS_MAX_PATH] = {0}; + strncpy(sendStr, contentPath, sizeof(sendStr)-1); + + IpcCommand c; + ipcInitialize(&c); + ipcAddSendStatic(&c, sendStr, sizeof(sendStr), 0); + + struct { + u64 magic; + u64 cmd_id; + u32 fsType; + u64 titleId; + } *raw; + + raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 8; + raw->fsType = fsType; + raw->titleId = titleId; + + Result rc = serviceIpcDispatch(s); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(s, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + serviceCreateSubservice(&out->s, s, &r, 0); + } + } + + return rc; +} + /* Missing FS File commands. */ Result fsFileOperateRange(FsFile* f, u32 op_id, u64 off, u64 len, FsRangeInfo *out) { IpcCommand c; diff --git a/stratosphere/ams_mitm/source/fs_mitm/fs_shim.h b/stratosphere/ams_mitm/source/fs_mitm/fs_shim.h index 730a2bfb5..cf6b28daf 100644 --- a/stratosphere/ams_mitm/source/fs_mitm/fs_shim.h +++ b/stratosphere/ams_mitm/source/fs_mitm/fs_shim.h @@ -20,6 +20,8 @@ typedef struct { Result fsOpenBisStorageFwd(Service* s, FsStorage* out, u32 PartitionId); Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out); Result fsOpenDataStorageByDataIdFwd(Service* s, FsStorageId storage_id, u64 data_id, FsStorage* out); +Result fsOpenFileSystemWithPatchFwd(Service* s, FsFileSystem* out, u64 titleId, FsFileSystemType fsType); +Result fsOpenFileSystemWithIdFwd(Service* s, FsFileSystem* out, u64 titleId, FsFileSystemType fsType, const char* contentPath); /* Missing FS File commands. */ Result fsFileOperateRange(FsFile* f, u32 op_id, u64 off, u64 len, FsRangeInfo *out); diff --git a/stratosphere/ams_mitm/source/fs_mitm/fsmitm_service.cpp b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_service.cpp index 3dfbb7a50..33f6eda10 100644 --- a/stratosphere/ams_mitm/source/fs_mitm/fsmitm_service.cpp +++ b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_service.cpp @@ -110,23 +110,49 @@ Result FsMitmService::OpenHblWebContentFileSystem(Out> out_fs, u64 title_id, u32 filesystem_type) { - FsDir d; - if (!Utils::IsWebAppletTid(this->title_id) || filesystem_type != FsFileSystemType_ContentManual || !Utils::IsHblTid(title_id) || - R_FAILED(Utils::OpenSdDir(AtmosphereHblWebContentDir, &d))) { - return RESULT_FORWARD_TO_SESSION; + /* Check for eligibility. */ + { + FsDir d; + if (!Utils::IsWebAppletTid(this->title_id) || filesystem_type != FsFileSystemType_ContentManual || !Utils::IsHblTid(title_id) || + R_FAILED(Utils::OpenSdDir(AtmosphereHblWebContentDir, &d))) { + return RESULT_FORWARD_TO_SESSION; + } + fsDirClose(&d); + } + + /* If there's an existing filesystem, don't override. */ + /* TODO: Multiplex, overriding existing content with HBL content. */ + { + FsFileSystem fs; + if (R_SUCCEEDED(fsOpenFileSystemWithPatchFwd(this->forward_service.get(), &fs, title_id, static_cast(filesystem_type)))) { + fsFsClose(&fs); + return RESULT_FORWARD_TO_SESSION; + } } - fsDirClose(&d); return this->OpenHblWebContentFileSystem(out_fs); } Result FsMitmService::OpenFileSystemWithId(Out> out_fs, InPointer path, u64 title_id, u32 filesystem_type) { - FsDir d; - if (!Utils::IsWebAppletTid(this->title_id) || filesystem_type != FsFileSystemType_ContentManual || !Utils::IsHblTid(title_id) || - R_FAILED(Utils::OpenSdDir(AtmosphereHblWebContentDir, &d))) { - return RESULT_FORWARD_TO_SESSION; + /* Check for eligibility. */ + { + FsDir d; + if (!Utils::IsWebAppletTid(this->title_id) || filesystem_type != FsFileSystemType_ContentManual || !Utils::IsHblTid(title_id) || + R_FAILED(Utils::OpenSdDir(AtmosphereHblWebContentDir, &d))) { + return RESULT_FORWARD_TO_SESSION; + } + fsDirClose(&d); + } + + /* If there's an existing filesystem, don't override. */ + /* TODO: Multiplex, overriding existing content with HBL content. */ + { + FsFileSystem fs; + if (R_SUCCEEDED(fsOpenFileSystemWithIdFwd(this->forward_service.get(), &fs, title_id, static_cast(filesystem_type), path.pointer))) { + fsFsClose(&fs); + return RESULT_FORWARD_TO_SESSION; + } } - fsDirClose(&d); return this->OpenHblWebContentFileSystem(out_fs); }