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