forked from eden-emu/eden
		
	bcat: Implement IDeliveryCacheFileService commands
Used to read the contents of files and access their metadata.
This commit is contained in:
		
							parent
							
								
									8812018c1d
								
							
						
					
					
						commit
						f352ad5c93
					
				
					 1 changed files with 117 additions and 0 deletions
				
			
		|  | @ -40,6 +40,123 @@ void Module::Interface::CreateBcatService(Kernel::HLERequestContext& ctx) { | |||
|     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.PushIpcInterface<IBcatService>(*backend); | ||||
| 
 | ||||
| class IDeliveryCacheFileService final : public ServiceFramework<IDeliveryCacheFileService> { | ||||
| public: | ||||
|     IDeliveryCacheFileService(FileSys::VirtualDir root_) | ||||
|         : ServiceFramework{"IDeliveryCacheFileService"}, root(std::move(root_)) { | ||||
|         // clang-format off
 | ||||
|         static const FunctionInfo functions[] = { | ||||
|             {0, &IDeliveryCacheFileService::Open, "Open"}, | ||||
|             {1, &IDeliveryCacheFileService::Read, "Read"}, | ||||
|             {2, &IDeliveryCacheFileService::GetSize, "GetSize"}, | ||||
|             {3, &IDeliveryCacheFileService::GetDigest, "GetDigest"}, | ||||
|         }; | ||||
|         // clang-format on
 | ||||
| 
 | ||||
|         RegisterHandlers(functions); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     void Open(Kernel::HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const auto dir_name_raw = rp.PopRaw<DirectoryName>(); | ||||
|         const auto file_name_raw = rp.PopRaw<FileName>(); | ||||
| 
 | ||||
|         const auto dir_name = | ||||
|             Common::StringFromFixedZeroTerminatedBuffer(dir_name_raw.data(), dir_name_raw.size()); | ||||
|         const auto file_name = | ||||
|             Common::StringFromFixedZeroTerminatedBuffer(file_name_raw.data(), file_name_raw.size()); | ||||
| 
 | ||||
|         LOG_DEBUG(Service_BCAT, "called, dir_name={}, file_name={}", dir_name, file_name); | ||||
| 
 | ||||
|         if (!VerifyNameValidDir(ctx, dir_name_raw) || !VerifyNameValidFile(ctx, file_name_raw)) | ||||
|             return; | ||||
| 
 | ||||
|         if (current_file != 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; | ||||
|         } | ||||
| 
 | ||||
|         const auto dir = root->GetSubdirectory(dir_name); | ||||
| 
 | ||||
|         if (dir == nullptr) { | ||||
|             LOG_ERROR(Service_BCAT, "The directory of name={} couldn't be opened!", dir_name); | ||||
|             IPC::ResponseBuilder rb{ctx, 2}; | ||||
|             rb.Push(ERROR_FAILED_OPEN_ENTITY); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         current_file = dir->GetFile(file_name); | ||||
| 
 | ||||
|         if (current_file == nullptr) { | ||||
|             LOG_ERROR(Service_BCAT, "The file of name={} couldn't be opened!", file_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) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const auto offset{rp.PopRaw<u64>()}; | ||||
| 
 | ||||
|         auto size = ctx.GetWriteBufferSize(); | ||||
| 
 | ||||
|         LOG_DEBUG(Service_BCAT, "called, offset={:016X}, size={:016X}", offset, size); | ||||
| 
 | ||||
|         if (current_file == nullptr) { | ||||
|             LOG_ERROR(Service_BCAT, "There is no file currently open!"); | ||||
|             IPC::ResponseBuilder rb{ctx, 2}; | ||||
|             rb.Push(ERROR_NO_OPEN_ENTITY); | ||||
|         } | ||||
| 
 | ||||
|         size = std::min(current_file->GetSize() - offset, size); | ||||
|         const auto buffer = current_file->ReadBytes(size, offset); | ||||
|         ctx.WriteBuffer(buffer); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 4}; | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|         rb.Push<u64>(buffer.size()); | ||||
|     } | ||||
| 
 | ||||
|     void GetSize(Kernel::HLERequestContext& ctx) { | ||||
|         LOG_DEBUG(Service_BCAT, "called"); | ||||
| 
 | ||||
|         if (current_file == nullptr) { | ||||
|             LOG_ERROR(Service_BCAT, "There is no file currently open!"); | ||||
|             IPC::ResponseBuilder rb{ctx, 2}; | ||||
|             rb.Push(ERROR_NO_OPEN_ENTITY); | ||||
|         } | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 4}; | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|         rb.Push<u64>(current_file->GetSize()); | ||||
|     } | ||||
| 
 | ||||
|     void GetDigest(Kernel::HLERequestContext& ctx) { | ||||
|         LOG_DEBUG(Service_BCAT, "called"); | ||||
| 
 | ||||
|         if (current_file == nullptr) { | ||||
|             LOG_ERROR(Service_BCAT, "There is no file currently open!"); | ||||
|             IPC::ResponseBuilder rb{ctx, 2}; | ||||
|             rb.Push(ERROR_NO_OPEN_ENTITY); | ||||
|         } | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 6}; | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|         rb.PushRaw(DigestFile(current_file)); | ||||
|     } | ||||
| 
 | ||||
|     FileSys::VirtualDir root; | ||||
|     FileSys::VirtualFile current_file; | ||||
| }; | ||||
| 
 | ||||
| class IDeliveryCacheDirectoryService final | ||||
|     : public ServiceFramework<IDeliveryCacheDirectoryService> { | ||||
| public: | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Zach Hilman
						Zach Hilman