src/platform/psp2/sce-vfs.c (view raw)
1/* Copyright (c) 2013-2015 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include <mgba-util/platform/psp2/sce-vfs.h>
7
8#include <psp2/io/dirent.h>
9
10#include <mgba-util/vfs.h>
11#include <mgba-util/memory.h>
12
13#ifndef SCE_CST_SIZE
14#define SCE_CST_SIZE 0x0004
15#endif
16
17struct VFileSce {
18 struct VFile d;
19
20 SceUID fd;
21};
22
23struct VDirEntrySce {
24 struct VDirEntry d;
25 SceIoDirent ent;
26};
27
28struct VDirSce {
29 struct VDir d;
30 struct VDirEntrySce de;
31 SceUID fd;
32 char* path;
33};
34
35static bool _vfsceClose(struct VFile* vf);
36static off_t _vfsceSeek(struct VFile* vf, off_t offset, int whence);
37static ssize_t _vfsceRead(struct VFile* vf, void* buffer, size_t size);
38static ssize_t _vfsceWrite(struct VFile* vf, const void* buffer, size_t size);
39static void* _vfsceMap(struct VFile* vf, size_t size, int flags);
40static void _vfsceUnmap(struct VFile* vf, void* memory, size_t size);
41static void _vfsceTruncate(struct VFile* vf, size_t size);
42static ssize_t _vfsceSize(struct VFile* vf);
43static bool _vfsceSync(struct VFile* vf, void* memory, size_t size);
44
45static bool _vdsceClose(struct VDir* vd);
46static void _vdsceRewind(struct VDir* vd);
47static struct VDirEntry* _vdsceListNext(struct VDir* vd);
48static struct VFile* _vdsceOpenFile(struct VDir* vd, const char* path, int mode);
49static struct VDir* _vdsceOpenDir(struct VDir* vd, const char* path);
50static bool _vdsceDeleteFile(struct VDir* vd, const char* path);
51
52static const char* _vdesceName(struct VDirEntry* vde);
53static enum VFSType _vdesceType(struct VDirEntry* vde);
54
55static bool _vdlsceClose(struct VDir* vd);
56static void _vdlsceRewind(struct VDir* vd);
57static struct VDirEntry* _vdlsceListNext(struct VDir* vd);
58static struct VFile* _vdlsceOpenFile(struct VDir* vd, const char* path, int mode);
59static struct VDir* _vdlsceOpenDir(struct VDir* vd, const char* path);
60static bool _vdlsceDeleteFile(struct VDir* vd, const char* path);
61
62static const char* _vdlesceName(struct VDirEntry* vde);
63static enum VFSType _vdlesceType(struct VDirEntry* vde);
64
65struct VFile* VFileOpenSce(const char* path, int flags, SceMode mode) {
66 struct VFileSce* vfsce = malloc(sizeof(struct VFileSce));
67 if (!vfsce) {
68 return 0;
69 }
70
71 vfsce->fd = sceIoOpen(path, flags, mode);
72 if (vfsce->fd < 0) {
73 free(vfsce);
74 return 0;
75 }
76
77 vfsce->d.close = _vfsceClose;
78 vfsce->d.seek = _vfsceSeek;
79 vfsce->d.read = _vfsceRead;
80 vfsce->d.readline = VFileReadline;
81 vfsce->d.write = _vfsceWrite;
82 vfsce->d.map = _vfsceMap;
83 vfsce->d.unmap = _vfsceUnmap;
84 vfsce->d.truncate = _vfsceTruncate;
85 vfsce->d.size = _vfsceSize;
86 vfsce->d.sync = _vfsceSync;
87
88 return &vfsce->d;
89}
90
91bool _vfsceClose(struct VFile* vf) {
92 struct VFileSce* vfsce = (struct VFileSce*) vf;
93 sceIoSyncByFd(vfsce->fd);
94 return sceIoClose(vfsce->fd) >= 0;
95}
96
97off_t _vfsceSeek(struct VFile* vf, off_t offset, int whence) {
98 struct VFileSce* vfsce = (struct VFileSce*) vf;
99 return sceIoLseek(vfsce->fd, offset, whence);
100}
101
102ssize_t _vfsceRead(struct VFile* vf, void* buffer, size_t size) {
103 struct VFileSce* vfsce = (struct VFileSce*) vf;
104 return sceIoRead(vfsce->fd, buffer, size);
105}
106
107ssize_t _vfsceWrite(struct VFile* vf, const void* buffer, size_t size) {
108 struct VFileSce* vfsce = (struct VFileSce*) vf;
109 return sceIoWrite(vfsce->fd, buffer, size);
110}
111
112static void* _vfsceMap(struct VFile* vf, size_t size, int flags) {
113 struct VFileSce* vfsce = (struct VFileSce*) vf;
114 UNUSED(flags);
115 void* buffer = anonymousMemoryMap(size);
116 if (buffer) {
117 SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR);
118 sceIoLseek(vfsce->fd, 0, SEEK_SET);
119 sceIoRead(vfsce->fd, buffer, size);
120 sceIoLseek(vfsce->fd, cur, SEEK_SET);
121 }
122 return buffer;
123}
124
125static void _vfsceUnmap(struct VFile* vf, void* memory, size_t size) {
126 struct VFileSce* vfsce = (struct VFileSce*) vf;
127 SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR);
128 sceIoLseek(vfsce->fd, 0, SEEK_SET);
129 sceIoWrite(vfsce->fd, memory, size);
130 sceIoLseek(vfsce->fd, cur, SEEK_SET);
131 sceIoSyncByFd(vfsce->fd);
132 mappedMemoryFree(memory, size);
133}
134
135static void _vfsceTruncate(struct VFile* vf, size_t size) {
136 struct VFileSce* vfsce = (struct VFileSce*) vf;
137 SceIoStat stat = { .st_size = size };
138 sceIoChstatByFd(vfsce->fd, &stat, SCE_CST_SIZE);
139}
140
141ssize_t _vfsceSize(struct VFile* vf) {
142 struct VFileSce* vfsce = (struct VFileSce*) vf;
143 SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR);
144 SceOff end = sceIoLseek(vfsce->fd, 0, SEEK_END);
145 sceIoLseek(vfsce->fd, cur, SEEK_SET);
146 return end;
147}
148
149bool _vfsceSync(struct VFile* vf, void* buffer, size_t size) {
150 struct VFileSce* vfsce = (struct VFileSce*) vf;
151 if (buffer && size) {
152 SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR);
153 sceIoLseek(vfsce->fd, 0, SEEK_SET);
154 int res = sceIoWrite(vfsce->fd, buffer, size);
155 sceIoLseek(vfsce->fd, cur, SEEK_SET);
156 return res == size;
157 }
158 return sceIoSyncByFd(vfsce->fd) >= 0;
159}
160
161struct VDir* VDirOpen(const char* path) {
162 if (!path || !path[0]) {
163 return VDeviceList();
164 }
165
166 SceUID dir = sceIoDopen(path);
167 if (dir < 0) {
168 return 0;
169 }
170
171 struct VDirSce* vd = malloc(sizeof(struct VDirSce));
172 vd->fd = dir;
173 vd->d.close = _vdsceClose;
174 vd->d.rewind = _vdsceRewind;
175 vd->d.listNext = _vdsceListNext;
176 vd->d.openFile = _vdsceOpenFile;
177 vd->d.openDir = _vdsceOpenDir;
178 vd->d.deleteFile = _vdsceDeleteFile;
179 vd->path = strdup(path);
180
181 vd->de.d.name = _vdesceName;
182 vd->de.d.type = _vdesceType;
183
184 return &vd->d;
185}
186
187bool _vdsceClose(struct VDir* vd) {
188 struct VDirSce* vdsce = (struct VDirSce*) vd;
189 if (sceIoDclose(vdsce->fd) < 0) {
190 return false;
191 }
192 free(vdsce->path);
193 free(vdsce);
194 return true;
195}
196
197void _vdsceRewind(struct VDir* vd) {
198 struct VDirSce* vdsce = (struct VDirSce*) vd;
199 sceIoDclose(vdsce->fd);
200 vdsce->fd = sceIoDopen(vdsce->path);
201}
202
203struct VDirEntry* _vdsceListNext(struct VDir* vd) {
204 struct VDirSce* vdsce = (struct VDirSce*) vd;
205 if (sceIoDread(vdsce->fd, &vdsce->de.ent) <= 0) {
206 return 0;
207 }
208 return &vdsce->de.d;
209}
210
211struct VFile* _vdsceOpenFile(struct VDir* vd, const char* path, int mode) {
212 struct VDirSce* vdsce = (struct VDirSce*) vd;
213 if (!path) {
214 return 0;
215 }
216 const char* dir = vdsce->path;
217 char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + strlen(PATH_SEP) + 1));
218 sprintf(combined, "%s%s%s", dir, PATH_SEP, path);
219
220 struct VFile* file = VFileOpen(combined, mode);
221 free(combined);
222 return file;
223}
224
225struct VDir* _vdsceOpenDir(struct VDir* vd, const char* path) {
226 struct VDirSce* vdsce = (struct VDirSce*) vd;
227 if (!path) {
228 return 0;
229 }
230 const char* dir = vdsce->path;
231 char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + strlen(PATH_SEP) + 1));
232 sprintf(combined, "%s%s%s", dir, PATH_SEP, path);
233
234 struct VDir* vd2 = VDirOpen(combined);
235 if (!vd2) {
236 vd2 = VDirOpenArchive(combined);
237 }
238 free(combined);
239 return vd2;
240}
241
242bool _vdsceDeleteFile(struct VDir* vd, const char* path) {
243 struct VDirSce* vdsce = (struct VDirSce*) vd;
244 if (!path) {
245 return 0;
246 }
247 const char* dir = vdsce->path;
248 char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + strlen(PATH_SEP) + 1));
249 sprintf(combined, "%s%s%s", dir, PATH_SEP, path);
250
251 bool ret = sceIoRemove(combined) >= 0;
252 free(combined);
253 return ret;
254}
255
256static const char* _vdesceName(struct VDirEntry* vde) {
257 struct VDirEntrySce* vdesce = (struct VDirEntrySce*) vde;
258 return vdesce->ent.d_name;
259}
260
261static enum VFSType _vdesceType(struct VDirEntry* vde) {
262 struct VDirEntrySce* vdesce = (struct VDirEntrySce*) vde;
263 if (SCE_S_ISDIR(vdesce->ent.d_stat.st_mode)) {
264 return VFS_DIRECTORY;
265 }
266 return VFS_FILE;
267}
268
269struct VDirEntrySceDevList {
270 struct VDirEntry d;
271 ssize_t index;
272 const char* name;
273};
274
275struct VDirSceDevList {
276 struct VDir d;
277 struct VDirEntrySceDevList vde;
278};
279
280static const char* _devs[] = {
281 "ux0:",
282 "ur0:",
283 "uma0:"
284};
285
286struct VDir* VDeviceList() {
287 struct VDirSceDevList* vd = malloc(sizeof(struct VDirSceDevList));
288 if (!vd) {
289 return 0;
290 }
291
292 vd->d.close = _vdlsceClose;
293 vd->d.rewind = _vdlsceRewind;
294 vd->d.listNext = _vdlsceListNext;
295 vd->d.openFile = _vdlsceOpenFile;
296 vd->d.openDir = _vdlsceOpenDir;
297 vd->d.deleteFile = _vdlsceDeleteFile;
298
299 vd->vde.d.name = _vdlesceName;
300 vd->vde.d.type = _vdlesceType;
301 vd->vde.index = -1;
302 vd->vde.name = 0;
303
304 return &vd->d;
305}
306
307static bool _vdlsceClose(struct VDir* vd) {
308 struct VDirSceDevList* vdl = (struct VDirSceDevList*) vd;
309 free(vdl);
310 return true;
311}
312
313static void _vdlsceRewind(struct VDir* vd) {
314 struct VDirSceDevList* vdl = (struct VDirSceDevList*) vd;
315 vdl->vde.name = NULL;
316 vdl->vde.index = -1;
317}
318
319static struct VDirEntry* _vdlsceListNext(struct VDir* vd) {
320 struct VDirSceDevList* vdl = (struct VDirSceDevList*) vd;
321 while (vdl->vde.index < 3) {
322 ++vdl->vde.index;
323 vdl->vde.name = _devs[vdl->vde.index];
324 SceUID dir = sceIoDopen(vdl->vde.name);
325 if (dir < 0) {
326 continue;
327 }
328 sceIoDclose(dir);
329 return &vdl->vde.d;
330 }
331 return 0;
332}
333
334static struct VFile* _vdlsceOpenFile(struct VDir* vd, const char* path, int mode) {
335 UNUSED(vd);
336 UNUSED(path);
337 UNUSED(mode);
338 return NULL;
339}
340
341static struct VDir* _vdlsceOpenDir(struct VDir* vd, const char* path) {
342 UNUSED(vd);
343 return VDirOpen(path);
344}
345
346static bool _vdlsceDeleteFile(struct VDir* vd, const char* path) {
347 UNUSED(vd);
348 UNUSED(path);
349 return false;
350}
351
352static const char* _vdlesceName(struct VDirEntry* vde) {
353 struct VDirEntrySceDevList* vdle = (struct VDirEntrySceDevList*) vde;
354 return vdle->name;
355}
356
357static enum VFSType _vdlesceType(struct VDirEntry* vde) {
358 UNUSED(vde);
359 return VFS_DIRECTORY;
360}
361
362bool VDirCreate(const char* path) {
363 // TODO: Verify vitasdk explanation of return values
364 sceIoMkdir(path, 0777);
365 return true;
366}