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