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
13struct VFileSce {
14 struct VFile d;
15
16 SceUID fd;
17};
18
19struct VDirEntrySce {
20 struct VDirEntry d;
21 SceIoDirent ent;
22};
23
24struct VDirSce {
25 struct VDir d;
26 struct VDirEntrySce de;
27 SceUID fd;
28 char* path;
29};
30
31static bool _vfsceClose(struct VFile* vf);
32static off_t _vfsceSeek(struct VFile* vf, off_t offset, int whence);
33static ssize_t _vfsceRead(struct VFile* vf, void* buffer, size_t size);
34static ssize_t _vfsceWrite(struct VFile* vf, const void* buffer, size_t size);
35static void* _vfsceMap(struct VFile* vf, size_t size, int flags);
36static void _vfsceUnmap(struct VFile* vf, void* memory, size_t size);
37static void _vfsceTruncate(struct VFile* vf, size_t size);
38static ssize_t _vfsceSize(struct VFile* vf);
39static bool _vfsceSync(struct VFile* vf, const void* memory, size_t size);
40
41static bool _vdsceClose(struct VDir* vd);
42static void _vdsceRewind(struct VDir* vd);
43static struct VDirEntry* _vdsceListNext(struct VDir* vd);
44static struct VFile* _vdsceOpenFile(struct VDir* vd, const char* path, int mode);
45static struct VDir* _vdsceOpenDir(struct VDir* vd, const char* path);
46static bool _vdsceDeleteFile(struct VDir* vd, const char* path);
47
48static const char* _vdesceName(struct VDirEntry* vde);
49static enum VFSType _vdesceType(struct VDirEntry* vde);
50
51struct VFile* VFileOpenSce(const char* path, int flags, SceMode mode) {
52 struct VFileSce* vfsce = malloc(sizeof(struct VFileSce));
53 if (!vfsce) {
54 return 0;
55 }
56
57 vfsce->fd = sceIoOpen(path, flags, mode);
58 if (vfsce->fd < 0) {
59 free(vfsce);
60 return 0;
61 }
62
63 vfsce->d.close = _vfsceClose;
64 vfsce->d.seek = _vfsceSeek;
65 vfsce->d.read = _vfsceRead;
66 vfsce->d.readline = VFileReadline;
67 vfsce->d.write = _vfsceWrite;
68 vfsce->d.map = _vfsceMap;
69 vfsce->d.unmap = _vfsceUnmap;
70 vfsce->d.truncate = _vfsceTruncate;
71 vfsce->d.size = _vfsceSize;
72 vfsce->d.sync = _vfsceSync;
73
74 return &vfsce->d;
75}
76
77bool _vfsceClose(struct VFile* vf) {
78 struct VFileSce* vfsce = (struct VFileSce*) vf;
79 sceIoSyncByFd(vfsce->fd);
80 return sceIoClose(vfsce->fd) >= 0;
81}
82
83off_t _vfsceSeek(struct VFile* vf, off_t offset, int whence) {
84 struct VFileSce* vfsce = (struct VFileSce*) vf;
85 return sceIoLseek(vfsce->fd, offset, whence);
86}
87
88ssize_t _vfsceRead(struct VFile* vf, void* buffer, size_t size) {
89 struct VFileSce* vfsce = (struct VFileSce*) vf;
90 return sceIoRead(vfsce->fd, buffer, size);
91}
92
93ssize_t _vfsceWrite(struct VFile* vf, const void* buffer, size_t size) {
94 struct VFileSce* vfsce = (struct VFileSce*) vf;
95 return sceIoWrite(vfsce->fd, buffer, size);
96}
97
98static void* _vfsceMap(struct VFile* vf, size_t size, int flags) {
99 struct VFileSce* vfsce = (struct VFileSce*) vf;
100 UNUSED(flags);
101 void* buffer = anonymousMemoryMap(size);
102 if (buffer) {
103 SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR);
104 sceIoLseek(vfsce->fd, 0, SEEK_SET);
105 sceIoRead(vfsce->fd, buffer, size);
106 sceIoLseek(vfsce->fd, cur, SEEK_SET);
107 }
108 return buffer;
109}
110
111static void _vfsceUnmap(struct VFile* vf, void* memory, size_t size) {
112 struct VFileSce* vfsce = (struct VFileSce*) vf;
113 SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR);
114 sceIoLseek(vfsce->fd, 0, SEEK_SET);
115 sceIoWrite(vfsce->fd, memory, size);
116 sceIoLseek(vfsce->fd, cur, SEEK_SET);
117 sceIoSyncByFd(vfsce->fd);
118 mappedMemoryFree(memory, size);
119}
120
121static void _vfsceTruncate(struct VFile* vf, size_t size) {
122 struct VFileSce* vfsce = (struct VFileSce*) vf;
123 SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR);
124 SceOff end = sceIoLseek(vfsce->fd, 0, SEEK_END);
125 if (end < size) {
126 uint8_t buffer[2048] = {};
127 size_t write = size - end;
128 while (write >= sizeof(buffer)) {
129 sceIoWrite(vfsce->fd, buffer, sizeof(buffer));
130 write -= sizeof(buffer);
131 }
132 if (write) {
133 sceIoWrite(vfsce->fd, buffer, write);
134 }
135 } // TODO: Else
136 sceIoLseek(vfsce->fd, cur, SEEK_SET);
137}
138
139ssize_t _vfsceSize(struct VFile* vf) {
140 struct VFileSce* vfsce = (struct VFileSce*) vf;
141 SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR);
142 SceOff end = sceIoLseek(vfsce->fd, 0, SEEK_END);
143 sceIoLseek(vfsce->fd, cur, SEEK_SET);
144 return end;
145}
146
147bool _vfsceSync(struct VFile* vf, const void* buffer, size_t size) {
148 struct VFileSce* vfsce = (struct VFileSce*) vf;
149 if (buffer && size) {
150 SceOff cur = sceIoLseek(vfsce->fd, 0, SEEK_CUR);
151 sceIoLseek(vfsce->fd, 0, SEEK_SET);
152 sceIoWrite(vfsce->fd, buffer, size);
153 sceIoLseek(vfsce->fd, cur, SEEK_SET);
154 }
155 return sceIoSyncByFd(vfsce->fd) >= 0;
156}
157
158struct VDir* VDirOpen(const char* path) {
159 SceUID dir = sceIoDopen(path);
160 if (dir < 0) {
161 return 0;
162 }
163
164 struct VDirSce* vd = malloc(sizeof(struct VDirSce));
165 vd->fd = dir;
166 vd->d.close = _vdsceClose;
167 vd->d.rewind = _vdsceRewind;
168 vd->d.listNext = _vdsceListNext;
169 vd->d.openFile = _vdsceOpenFile;
170 vd->d.openDir = _vdsceOpenDir;
171 vd->d.deleteFile = _vdsceDeleteFile;
172 vd->path = strdup(path);
173
174 vd->de.d.name = _vdesceName;
175 vd->de.d.type = _vdesceType;
176
177 return &vd->d;
178}
179
180bool _vdsceClose(struct VDir* vd) {
181 struct VDirSce* vdsce = (struct VDirSce*) vd;
182 if (sceIoDclose(vdsce->fd) < 0) {
183 return false;
184 }
185 free(vdsce->path);
186 free(vdsce);
187 return true;
188}
189
190void _vdsceRewind(struct VDir* vd) {
191 struct VDirSce* vdsce = (struct VDirSce*) vd;
192 sceIoDclose(vdsce->fd);
193 vdsce->fd = sceIoDopen(vdsce->path);
194}
195
196struct VDirEntry* _vdsceListNext(struct VDir* vd) {
197 struct VDirSce* vdsce = (struct VDirSce*) vd;
198 if (sceIoDread(vdsce->fd, &vdsce->de.ent) <= 0) {
199 return 0;
200 }
201 return &vdsce->de.d;
202}
203
204struct VFile* _vdsceOpenFile(struct VDir* vd, const char* path, int mode) {
205 struct VDirSce* vdsce = (struct VDirSce*) vd;
206 if (!path) {
207 return 0;
208 }
209 const char* dir = vdsce->path;
210 char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + strlen(PATH_SEP) + 1));
211 sprintf(combined, "%s%s%s", dir, PATH_SEP, path);
212
213 struct VFile* file = VFileOpen(combined, mode);
214 free(combined);
215 return file;
216}
217
218struct VDir* _vdsceOpenDir(struct VDir* vd, const char* path) {
219 struct VDirSce* vdsce = (struct VDirSce*) vd;
220 if (!path) {
221 return 0;
222 }
223 const char* dir = vdsce->path;
224 char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + strlen(PATH_SEP) + 1));
225 sprintf(combined, "%s%s%s", dir, PATH_SEP, path);
226
227 struct VDir* vd2 = VDirOpen(combined);
228 if (!vd2) {
229 vd2 = VDirOpenArchive(combined);
230 }
231 free(combined);
232 return vd2;
233}
234
235bool _vdsceDeleteFile(struct VDir* vd, const char* path) {
236 struct VDirSce* vdsce = (struct VDirSce*) vd;
237 if (!path) {
238 return 0;
239 }
240 const char* dir = vdsce->path;
241 char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + strlen(PATH_SEP) + 1));
242 sprintf(combined, "%s%s%s", dir, PATH_SEP, path);
243
244 bool ret = sceIoRemove(combined) >= 0;
245 free(combined);
246 return ret;
247}
248
249static const char* _vdesceName(struct VDirEntry* vde) {
250 struct VDirEntrySce* vdesce = (struct VDirEntrySce*) vde;
251 return vdesce->ent.d_name;
252}
253
254static enum VFSType _vdesceType(struct VDirEntry* vde) {
255 struct VDirEntrySce* vdesce = (struct VDirEntrySce*) vde;
256 if (SCE_S_ISDIR(vdesce->ent.d_stat.st_mode)) {
257 return VFS_DIRECTORY;
258 }
259 return VFS_FILE;
260}