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
							
								
									ee01e3163a
								
							
						
					
					
						commit
						dc3f624408
					
				
					 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}; |     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     rb.PushIpcInterface<IBcatService>(*backend); |     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> { | class IDeliveryCacheStorageService final : public ServiceFramework<IDeliveryCacheStorageService> { | ||||||
| public: | public: | ||||||
|     IDeliveryCacheStorageService(FileSys::VirtualDir root_) |     IDeliveryCacheStorageService(FileSys::VirtualDir root_) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Zach Hilman
						Zach Hilman