diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index 92eb4ef045..db304812c4 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -92,15 +92,15 @@ void File::Read(Kernel::HLERequestContext& ctx) { LOG_TRACE(Service_FS, "Read %s: offset=0x%" PRIx64 " length=0x%08X", GetName().c_str(), offset, length); - const SessionSlot& file = GetSessionSlot(ctx.Session()); + const FileSessionSlot* file = GetSessionData(ctx.Session()); - if (file.subfile && length > file.size) { + if (file->subfile && length > file->size) { LOG_WARNING(Service_FS, "Trying to read beyond the subfile size, truncating"); - length = file.size; + length = file->size; } // This file session might have a specific offset from where to start reading, apply it. - offset += file.offset; + offset += file->offset; if (offset + length > backend->GetSize()) { LOG_ERROR(Service_FS, "Reading from out of bounds offset=0x%" PRIx64 @@ -134,10 +134,10 @@ void File::Write(Kernel::HLERequestContext& ctx) { IPC::RequestBuilder rb = rp.MakeBuilder(2, 2); - const SessionSlot& file = GetSessionSlot(ctx.Session()); + const FileSessionSlot* file = GetSessionData(ctx.Session()); // Subfiles can not be written to - if (file.subfile) { + if (file->subfile) { rb.Push(FileSys::ERROR_UNSUPPORTED_OPEN_FLAGS); rb.Push(0); rb.PushMappedBuffer(buffer); @@ -160,28 +160,28 @@ void File::Write(Kernel::HLERequestContext& ctx) { void File::GetSize(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx, 0x0804, 0, 0); - const SessionSlot& file = GetSessionSlot(ctx.Session()); + const FileSessionSlot* file = GetSessionData(ctx.Session()); IPC::RequestBuilder rb = rp.MakeBuilder(3, 0); rb.Push(RESULT_SUCCESS); - rb.Push(file.size); + rb.Push(file->size); } void File::SetSize(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx, 0x0805, 2, 0); u64 size = rp.Pop(); - SessionSlot& file = GetSessionSlot(ctx.Session()); + FileSessionSlot* file = GetSessionData(ctx.Session()); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); // SetSize can not be called on subfiles. - if (file.subfile) { + if (file->subfile) { rb.Push(FileSys::ERROR_UNSUPPORTED_OPEN_FLAGS); return; } - file.size = size; + file->size = size; backend->SetSize(size); rb.Push(RESULT_SUCCESS); } @@ -190,9 +190,9 @@ void File::Close(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx, 0x0808, 0, 0); // TODO(Subv): Only close the backend if this client is the only one left. - if (session_slots.size() > 1) + if (connected_sessions.size() > 1) LOG_WARNING(Service_FS, "Closing File backend but %zu clients still connected", - session_slots.size()); + connected_sessions.size()); backend->Close(); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); @@ -204,10 +204,10 @@ void File::Flush(Kernel::HLERequestContext& ctx) { IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - const SessionSlot& file = GetSessionSlot(ctx.Session()); + const FileSessionSlot* file = GetSessionData(ctx.Session()); // Subfiles can not be flushed. - if (file.subfile) { + if (file->subfile) { rb.Push(FileSys::ERROR_UNSUPPORTED_OPEN_FLAGS); return; } @@ -219,8 +219,8 @@ void File::Flush(Kernel::HLERequestContext& ctx) { void File::SetPriority(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx, 0x080A, 1, 0); - SessionSlot& file = GetSessionSlot(ctx.Session()); - file.priority = rp.Pop(); + FileSessionSlot* file = GetSessionData(ctx.Session()); + file->priority = rp.Pop(); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); rb.Push(RESULT_SUCCESS); @@ -228,11 +228,11 @@ void File::SetPriority(Kernel::HLERequestContext& ctx) { void File::GetPriority(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx, 0x080B, 0, 0); - const SessionSlot& file = GetSessionSlot(ctx.Session()); + const FileSessionSlot* file = GetSessionData(ctx.Session()); IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); rb.Push(RESULT_SUCCESS); - rb.Push(file.priority); + rb.Push(file->priority); } void File::OpenLinkFile(Kernel::HLERequestContext& ctx) { @@ -246,16 +246,13 @@ void File::OpenLinkFile(Kernel::HLERequestContext& ctx) { auto server = std::get>(sessions); ClientConnected(server); - const SessionSlot& original_file = GetSessionSlot(ctx.Session()); + FileSessionSlot* slot = GetSessionData(server); + const FileSessionSlot* original_file = GetSessionData(ctx.Session()); - SessionSlot slot{}; - slot.priority = original_file.priority; - slot.offset = 0; - slot.size = backend->GetSize(); - slot.session = server; - slot.subfile = false; - - session_slots.emplace_back(std::move(slot)); + slot->priority = original_file->priority; + slot->offset = 0; + slot->size = backend->GetSize(); + slot->subfile = false; rb.Push(RESULT_SUCCESS); rb.PushMoveObjects(std::get>(sessions)); @@ -268,9 +265,9 @@ void File::OpenSubFile(Kernel::HLERequestContext& ctx) { IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); - const SessionSlot& original_file = GetSessionSlot(ctx.Session()); + const FileSessionSlot* original_file = GetSessionData(ctx.Session()); - if (original_file.subfile) { + if (original_file->subfile) { // OpenSubFile can not be called on a file which is already as subfile rb.Push(FileSys::ERROR_UNSUPPORTED_OPEN_FLAGS); return; @@ -285,7 +282,7 @@ void File::OpenSubFile(Kernel::HLERequestContext& ctx) { // TODO(Subv): Check for overflow and return ERR_WRITE_BEYOND_END - if (end > original_file.size) { + if (end > original_file->size) { rb.Push(FileSys::ERR_WRITE_BEYOND_END); return; } @@ -297,47 +294,26 @@ void File::OpenSubFile(Kernel::HLERequestContext& ctx) { auto server = std::get>(sessions); ClientConnected(server); - SessionSlot slot{}; - slot.priority = original_file.priority; - slot.offset = offset; - slot.size = size; - slot.session = server; - slot.subfile = true; - - session_slots.emplace_back(std::move(slot)); + FileSessionSlot* slot = GetSessionData(server); + slot->priority = original_file->priority; + slot->offset = offset; + slot->size = size; + slot->subfile = true; rb.Push(RESULT_SUCCESS); rb.PushMoveObjects(std::get>(sessions)); } -File::SessionSlot& File::GetSessionSlot(Kernel::SharedPtr session) { - auto itr = std::find_if(session_slots.begin(), session_slots.end(), - [&](const SessionSlot& slot) { return slot.session == session; }); - ASSERT(itr != session_slots.end()); - return *itr; -} - -void File::ClientDisconnected(Kernel::SharedPtr server_session) { - session_slots.erase( - std::remove_if(session_slots.begin(), session_slots.end(), - [&](const SessionSlot& slot) { return slot.session == server_session; }), - session_slots.end()); - SessionRequestHandler::ClientDisconnected(server_session); -} - Kernel::SharedPtr File::Connect() { auto sessions = Kernel::ServerSession::CreateSessionPair(GetName()); auto server = std::get>(sessions); ClientConnected(server); - SessionSlot slot{}; - slot.priority = 0; - slot.offset = 0; - slot.size = backend->GetSize(); - slot.session = server; - slot.subfile = false; - - session_slots.emplace_back(std::move(slot)); + FileSessionSlot* slot = GetSessionData(server); + slot->priority = 0; + slot->offset = 0; + slot->size = backend->GetSize(); + slot->subfile = false; return std::get>(sessions); } diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index 65f6f207aa..df4c902d0e 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h @@ -50,9 +50,16 @@ enum class MediaType : u32 { NAND = 0, SDMC = 1, GameCard = 2 }; typedef u64 ArchiveHandle; +struct FileSessionSlot : public Kernel::SessionRequestHandler::SessionDataBase { + u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means + u64 offset; ///< Offset that this session will start reading from. + u64 size; ///< Max size of the file that this session is allowed to access + bool subfile; ///< Whether this file was opened via OpenSubFile or not. +}; + // TODO: File is not a real service, but it can still utilize ServiceFramework::RegisterHandlers. // Consider splitting ServiceFramework interface. -class File final : public ServiceFramework { +class File final : public ServiceFramework { public: File(std::unique_ptr&& backend, const FileSys::Path& path); ~File() = default; @@ -67,8 +74,6 @@ public: /// Creates a new session to this File and returns the ClientSession part of the connection. Kernel::SharedPtr Connect(); - void ClientDisconnected(Kernel::SharedPtr server_session) override; - private: void Read(Kernel::HLERequestContext& ctx); void Write(Kernel::HLERequestContext& ctx); @@ -80,18 +85,6 @@ private: void GetPriority(Kernel::HLERequestContext& ctx); void OpenLinkFile(Kernel::HLERequestContext& ctx); void OpenSubFile(Kernel::HLERequestContext& ctx); - - struct SessionSlot { - Kernel::SharedPtr session; ///< The session that this slot refers to. - u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means - u64 offset; ///< Offset that this session will start reading from. - u64 size; ///< Max size of the file that this session is allowed to access - bool subfile; ///< Whether this file was opened via OpenSubFile or not. - }; - - std::vector session_slots; - - SessionSlot& GetSessionSlot(Kernel::SharedPtr session); }; class Directory final : public Kernel::SessionRequestHandler {