forked from eden-emu/eden
		
	bcat: Implement IDeliveryCacheDirectoryService commands
Used to list and get directories at the root level.
This commit is contained in:
		
							parent
							
								
									862131ead9
								
							
						
					
					
						commit
						8812018c1d
					
				
					 1 changed files with 99 additions and 0 deletions
				
			
		|  | @ -40,6 +40,105 @@ void Module::Interface::CreateBcatService(Kernel::HLERequestContext& ctx) { | |||
|     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.PushIpcInterface<IBcatService>(*backend); | ||||
| class IDeliveryCacheDirectoryService final | ||||
|     : public ServiceFramework<IDeliveryCacheDirectoryService> { | ||||
| public: | ||||
|     IDeliveryCacheDirectoryService(FileSys::VirtualDir root_) | ||||
|         : ServiceFramework{"IDeliveryCacheDirectoryService"}, root(std::move(root_)) { | ||||
|         // clang-format off
 | ||||
|         static const FunctionInfo functions[] = { | ||||
|             {0, &IDeliveryCacheDirectoryService::Open, "Open"}, | ||||
|             {1, &IDeliveryCacheDirectoryService::Read, "Read"}, | ||||
|             {2, &IDeliveryCacheDirectoryService::GetCount, "GetCount"}, | ||||
|         }; | ||||
|         // clang-format on
 | ||||
| 
 | ||||
|         RegisterHandlers(functions); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     void Open(Kernel::HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const auto name_raw = rp.PopRaw<DirectoryName>(); | ||||
|         const auto name = | ||||
|             Common::StringFromFixedZeroTerminatedBuffer(name_raw.data(), name_raw.size()); | ||||
| 
 | ||||
|         LOG_DEBUG(Service_BCAT, "called, name={}", name); | ||||
| 
 | ||||
|         if (!VerifyNameValidDir(ctx, name_raw)) | ||||
|             return; | ||||
| 
 | ||||
|         if (current_dir != nullptr) { | ||||
|             LOG_ERROR(Service_BCAT, "A file has already been opened on this interface!"); | ||||
|             IPC::ResponseBuilder rb{ctx, 2}; | ||||
|             rb.Push(ERROR_ENTITY_ALREADY_OPEN); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         current_dir = root->GetSubdirectory(name); | ||||
| 
 | ||||
|         if (current_dir == nullptr) { | ||||
|             LOG_ERROR(Service_BCAT, "Failed to open the directory name={}!", name); | ||||
|             IPC::ResponseBuilder rb{ctx, 2}; | ||||
|             rb.Push(ERROR_FAILED_OPEN_ENTITY); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|     } | ||||
| 
 | ||||
|     void Read(Kernel::HLERequestContext& ctx) { | ||||
|         auto write_size = ctx.GetWriteBufferSize() / sizeof(DeliveryCacheDirectoryEntry); | ||||
| 
 | ||||
|         LOG_DEBUG(Service_BCAT, "called, write_size={:016X}", write_size); | ||||
| 
 | ||||
|         if (current_dir == nullptr) { | ||||
|             LOG_ERROR(Service_BCAT, "There is no open directory!"); | ||||
|             IPC::ResponseBuilder rb{ctx, 2}; | ||||
|             rb.Push(ERROR_NO_OPEN_ENTITY); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         const auto files = current_dir->GetFiles(); | ||||
|         write_size = std::min(write_size, files.size()); | ||||
|         std::vector<DeliveryCacheDirectoryEntry> entries(write_size); | ||||
|         std::transform( | ||||
|             files.begin(), files.begin() + write_size, entries.begin(), [](const auto& file) { | ||||
|                 FileName name{}; | ||||
|                 std::memcpy(name.data(), file->GetName().data(), | ||||
|                             std::min(file->GetName().size(), name.size())); | ||||
|                 return DeliveryCacheDirectoryEntry{name, file->GetSize(), DigestFile(file)}; | ||||
|             }); | ||||
| 
 | ||||
|         ctx.WriteBuffer(entries); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 3}; | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|         rb.Push<u32>(write_size * sizeof(DeliveryCacheDirectoryEntry)); | ||||
|     } | ||||
| 
 | ||||
|     void GetCount(Kernel::HLERequestContext& ctx) { | ||||
|         LOG_DEBUG(Service_BCAT, "called"); | ||||
| 
 | ||||
|         if (current_dir == nullptr) { | ||||
|             LOG_ERROR(Service_BCAT, "There is no open directory!"); | ||||
|             IPC::ResponseBuilder rb{ctx, 2}; | ||||
|             rb.Push(ERROR_NO_OPEN_ENTITY); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         const auto files = current_dir->GetFiles(); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 3}; | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|         rb.Push<u32>(files.size()); | ||||
|     } | ||||
| 
 | ||||
|     FileSys::VirtualDir root; | ||||
|     FileSys::VirtualDir current_dir; | ||||
| }; | ||||
| 
 | ||||
| class IDeliveryCacheStorageService final : public ServiceFramework<IDeliveryCacheStorageService> { | ||||
| public: | ||||
|     IDeliveryCacheStorageService(FileSys::VirtualDir root_) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Zach Hilman
						Zach Hilman