summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Zach Hilman2019-04-28 18:54:26 -0400
committerGravatar Zach Hilman2019-09-30 17:23:26 -0400
commitf352ad5c93aa0266cba8b4c15ee3f0c5f0b0aed2 (patch)
treee51758383c6fa3da83d9d940fabc91e52d22fda7 /src
parentbcat: Implement IDeliveryCacheDirectoryService commands (diff)
downloadyuzu-f352ad5c93aa0266cba8b4c15ee3f0c5f0b0aed2.tar.gz
yuzu-f352ad5c93aa0266cba8b4c15ee3f0c5f0b0aed2.tar.xz
yuzu-f352ad5c93aa0266cba8b4c15ee3f0c5f0b0aed2.zip
bcat: Implement IDeliveryCacheFileService commands
Used to read the contents of files and access their metadata.
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/bcat/module.cpp117
1 files changed, 117 insertions, 0 deletions
diff --git a/src/core/hle/service/bcat/module.cpp b/src/core/hle/service/bcat/module.cpp
index 6645599f2..25f68ed63 100644
--- a/src/core/hle/service/bcat/module.cpp
+++ b/src/core/hle/service/bcat/module.cpp
@@ -40,6 +40,123 @@ void Module::Interface::CreateBcatService(Kernel::HLERequestContext& ctx) {
40 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 40 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
41 rb.Push(RESULT_SUCCESS); 41 rb.Push(RESULT_SUCCESS);
42 rb.PushIpcInterface<IBcatService>(*backend); 42 rb.PushIpcInterface<IBcatService>(*backend);
43
44class IDeliveryCacheFileService final : public ServiceFramework<IDeliveryCacheFileService> {
45public:
46 IDeliveryCacheFileService(FileSys::VirtualDir root_)
47 : ServiceFramework{"IDeliveryCacheFileService"}, root(std::move(root_)) {
48 // clang-format off
49 static const FunctionInfo functions[] = {
50 {0, &IDeliveryCacheFileService::Open, "Open"},
51 {1, &IDeliveryCacheFileService::Read, "Read"},
52 {2, &IDeliveryCacheFileService::GetSize, "GetSize"},
53 {3, &IDeliveryCacheFileService::GetDigest, "GetDigest"},
54 };
55 // clang-format on
56
57 RegisterHandlers(functions);
58 }
59
60private:
61 void Open(Kernel::HLERequestContext& ctx) {
62 IPC::RequestParser rp{ctx};
63 const auto dir_name_raw = rp.PopRaw<DirectoryName>();
64 const auto file_name_raw = rp.PopRaw<FileName>();
65
66 const auto dir_name =
67 Common::StringFromFixedZeroTerminatedBuffer(dir_name_raw.data(), dir_name_raw.size());
68 const auto file_name =
69 Common::StringFromFixedZeroTerminatedBuffer(file_name_raw.data(), file_name_raw.size());
70
71 LOG_DEBUG(Service_BCAT, "called, dir_name={}, file_name={}", dir_name, file_name);
72
73 if (!VerifyNameValidDir(ctx, dir_name_raw) || !VerifyNameValidFile(ctx, file_name_raw))
74 return;
75
76 if (current_file != nullptr) {
77 LOG_ERROR(Service_BCAT, "A file has already been opened on this interface!");
78 IPC::ResponseBuilder rb{ctx, 2};
79 rb.Push(ERROR_ENTITY_ALREADY_OPEN);
80 return;
81 }
82
83 const auto dir = root->GetSubdirectory(dir_name);
84
85 if (dir == nullptr) {
86 LOG_ERROR(Service_BCAT, "The directory of name={} couldn't be opened!", dir_name);
87 IPC::ResponseBuilder rb{ctx, 2};
88 rb.Push(ERROR_FAILED_OPEN_ENTITY);
89 return;
90 }
91
92 current_file = dir->GetFile(file_name);
93
94 if (current_file == nullptr) {
95 LOG_ERROR(Service_BCAT, "The file of name={} couldn't be opened!", file_name);
96 IPC::ResponseBuilder rb{ctx, 2};
97 rb.Push(ERROR_FAILED_OPEN_ENTITY);
98 return;
99 }
100
101 IPC::ResponseBuilder rb{ctx, 2};
102 rb.Push(RESULT_SUCCESS);
103 }
104
105 void Read(Kernel::HLERequestContext& ctx) {
106 IPC::RequestParser rp{ctx};
107 const auto offset{rp.PopRaw<u64>()};
108
109 auto size = ctx.GetWriteBufferSize();
110
111 LOG_DEBUG(Service_BCAT, "called, offset={:016X}, size={:016X}", offset, size);
112
113 if (current_file == nullptr) {
114 LOG_ERROR(Service_BCAT, "There is no file currently open!");
115 IPC::ResponseBuilder rb{ctx, 2};
116 rb.Push(ERROR_NO_OPEN_ENTITY);
117 }
118
119 size = std::min(current_file->GetSize() - offset, size);
120 const auto buffer = current_file->ReadBytes(size, offset);
121 ctx.WriteBuffer(buffer);
122
123 IPC::ResponseBuilder rb{ctx, 4};
124 rb.Push(RESULT_SUCCESS);
125 rb.Push<u64>(buffer.size());
126 }
127
128 void GetSize(Kernel::HLERequestContext& ctx) {
129 LOG_DEBUG(Service_BCAT, "called");
130
131 if (current_file == nullptr) {
132 LOG_ERROR(Service_BCAT, "There is no file currently open!");
133 IPC::ResponseBuilder rb{ctx, 2};
134 rb.Push(ERROR_NO_OPEN_ENTITY);
135 }
136
137 IPC::ResponseBuilder rb{ctx, 4};
138 rb.Push(RESULT_SUCCESS);
139 rb.Push<u64>(current_file->GetSize());
140 }
141
142 void GetDigest(Kernel::HLERequestContext& ctx) {
143 LOG_DEBUG(Service_BCAT, "called");
144
145 if (current_file == nullptr) {
146 LOG_ERROR(Service_BCAT, "There is no file currently open!");
147 IPC::ResponseBuilder rb{ctx, 2};
148 rb.Push(ERROR_NO_OPEN_ENTITY);
149 }
150
151 IPC::ResponseBuilder rb{ctx, 6};
152 rb.Push(RESULT_SUCCESS);
153 rb.PushRaw(DigestFile(current_file));
154 }
155
156 FileSys::VirtualDir root;
157 FileSys::VirtualFile current_file;
158};
159
43class IDeliveryCacheDirectoryService final 160class IDeliveryCacheDirectoryService final
44 : public ServiceFramework<IDeliveryCacheDirectoryService> { 161 : public ServiceFramework<IDeliveryCacheDirectoryService> {
45public: 162public: