diff --git a/stratosphere/loader/source/ldr_ecs.cpp b/stratosphere/loader/source/ldr_ecs.cpp index 91da78849..a49a3ebd7 100644 --- a/stratosphere/loader/source/ldr_ecs.cpp +++ b/stratosphere/loader/source/ldr_ecs.cpp @@ -28,15 +28,41 @@ namespace ams::ldr::ecs { NON_COPYABLE(ExternalContentSource); NON_MOVEABLE(ExternalContentSource); private: + bool has_mounted = false; char device_name[DeviceNameSizeMax]; + os::ManagedHandle client; + + Result Mount() { + /* Create service. */ + Service srv; + serviceCreate(&srv, client.Move()); + FsFileSystem fs = { srv }; + auto fs_guard = SCOPE_GUARD { fsFsClose(&fs); }; + + /* Try to mount. */ + R_UNLESS(fsdevMountDevice(device_name, fs) >= 0, fs::ResultMountNameAlreadyExists()); + fs_guard.Cancel(); + + this->has_mounted = true; + return ResultSuccess(); + } public: - ExternalContentSource(const char *dn) { + ExternalContentSource(const char *dn, os::ManagedHandle client) : client(std::move(client)) { std::strncpy(this->device_name, dn, sizeof(this->device_name)); this->device_name[sizeof(this->device_name) - 1] = '\0'; } + Result EnsureMounted() { + if (!this->has_mounted) { + return Mount(); + } + return ResultSuccess(); + } + ~ExternalContentSource() { - fsdevUnmountDevice(this->device_name); + if (this->has_mounted) { + fsdevUnmountDevice(this->device_name); + } } const char *GetDeviceName() const { @@ -54,6 +80,10 @@ namespace ams::ldr::ecs { if (it == g_map.end()) { return nullptr; } + if (R_FAILED(it->second.EnsureMounted())) { + g_map.erase(it); + return nullptr; + } return it->second.GetDeviceName(); } @@ -72,18 +102,13 @@ namespace ams::ldr::ecs { os::ManagedHandle server, client; R_TRY(svcCreateSession(server.GetPointer(), client.GetPointer(), 0, 0)); - /* Create service. */ - Service srv; - serviceCreate(&srv, client.Move()); - FsFileSystem fs = { srv }; - auto fs_guard = SCOPE_GUARD { fsFsClose(&fs); }; - - /* Try to mount. */ - R_UNLESS(fsdevMountDevice(device_name, fs) >= 0, fs::ResultMountNameAlreadyExists()); - fs_guard.Cancel(); + /* Do not create service yet. */ + /* Defer until we've handed the server side back so we don't deadlock on querying pointer buffer size. */ /* Add to map. */ - g_map.emplace(static_cast(program_id), device_name); + g_map.emplace(std::piecewise_construct, + std::make_tuple(static_cast(program_id)), + std::make_tuple(device_name, std::move(client))); *out = server.Move(); return ResultSuccess(); }