sdk-core v2026.11.05
PS2 SDK - core tier (build-critical EE/IOP modules)
Loading...
Searching...
No Matches
fileXio_ps2sdk.c
Go to the documentation of this file.
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# (C)2001, Gustavo Scotti (gustavo@scotti.com)
7# (c) 2003 Marcus R. Brown <mrbrown@0xd6.org>
8# (c) 2023 Francisco Javier Trujillo Mata <fjtrujy@gmail.com>
9# Licenced under Academic Free License version 2.0
10# Review ps2sdk README & LICENSE files for further details.
11*/
12
17
18#include <ps2sdkapi.h>
19#include <string.h>
20#include <stdio.h>
21#include <errno.h>
22#include <stdlib.h>
23#define NEWLIB_PORT_AWARE
24#include <fileio.h>
25#include <fileXio_rpc.h>
26#include "iox_stat.h"
27
28typedef struct _fxio_file_info_
29{
30 // cppcheck-suppress unusedStructMember
31 int fd;
32 // cppcheck-suppress unusedStructMember
33 char filename[];
34} _fxio_file_info_t;
35
36_libcglue_fdman_path_ops_t __fileXio_fdman_path_ops;
37_libcglue_fdman_fd_ops_t __fileXio_fdman_ops_file;
38_libcglue_fdman_fd_ops_t __fileXio_fdman_ops_dir;
39
40extern void __fileXioOpsInitializeImpl(void);
41
42__attribute__((constructor))
43static void __fileXioOpsInitialize(void)
44{
45 __fileXioOpsInitializeImpl();
46}
47
48
49#define IOP_O_RDONLY 0x0001
50#define IOP_O_WRONLY 0x0002
51#define IOP_O_RDWR 0x0003
52#define IOP_O_DIROPEN 0x0008 // Internal use for dopen
53#define IOP_O_NBLOCK 0x0010
54#define IOP_O_APPEND 0x0100
55#define IOP_O_CREAT 0x0200
56#define IOP_O_TRUNC 0x0400
57#define IOP_O_EXCL 0x0800
58#define IOP_O_NOWAIT 0x8000
59
60int __fileXioOpenHelper(_libcglue_fdman_fd_info_t *info, const char *buf, int flags, mode_t mode)
61{
62 int iop_flags = 0;
63 int is_dir = 0;
64 int iop_fd;
65
66 // newlib flags differ from iop flags
67 if ((flags & 3) == O_RDONLY) iop_flags |= IOP_O_RDONLY;
68 if ((flags & 3) == O_WRONLY) iop_flags |= IOP_O_WRONLY;
69 if ((flags & 3) == O_RDWR ) iop_flags |= IOP_O_RDWR;
70 if (flags & O_NONBLOCK) iop_flags |= IOP_O_NBLOCK;
71 if (flags & O_APPEND) iop_flags |= IOP_O_APPEND;
72 if (flags & O_CREAT) iop_flags |= IOP_O_CREAT;
73 if (flags & O_TRUNC) iop_flags |= IOP_O_TRUNC;
74 if (flags & O_EXCL) iop_flags |= IOP_O_EXCL;
75 //if (flags & O_???) iop_flags |= IOP_O_NOWAIT;
76 if (flags & O_DIRECTORY) {
77 iop_flags |= IOP_O_DIROPEN;
78 is_dir = 1;
79 }
80
81 iop_fd = is_dir ? fileXioDopen(buf) : fileXioOpen(buf, iop_flags, mode);
82 if (iop_fd >= 0) {
83 _fxio_file_info_t *userdata;
84 int buf_len;
85
86 buf_len = strlen(buf);
87 userdata = malloc(sizeof(_fxio_file_info_t) + buf_len + 1);
88 if (userdata == NULL)
89 {
90 return -ENOMEM;
91 }
92 userdata->fd = iop_fd;
93 memcpy(userdata->filename, buf, buf_len);
94 userdata->filename[buf_len] = '\x00';
95 info->userdata = (void *)userdata;
96 info->ops = is_dir ? &__fileXio_fdman_ops_dir : &__fileXio_fdman_ops_file;
97 return 0;
98 }
99 return iop_fd;
100}
101
102int __fileXioGetFdHelper(void *userdata)
103{
104 _fxio_file_info_t *finfo;
105
106 if (userdata == NULL)
107 {
108 return -EINVAL;
109 }
110
111 finfo = (_fxio_file_info_t *)userdata;
112 return finfo->fd;
113}
114
115char *__fileXioGetFilenameHelper(void *userdata)
116{
117 _fxio_file_info_t *finfo;
118
119 if (userdata == NULL)
120 {
121 return NULL;
122 }
123
124 finfo = (_fxio_file_info_t *)userdata;
125 return finfo->filename;
126}
127
128static time_t io_to_posix_time(const unsigned char *ps2time)
129{
130 struct tm tim;
131 tim.tm_sec = ps2time[1];
132 tim.tm_min = ps2time[2];
133 tim.tm_hour = ps2time[3];
134 tim.tm_mday = ps2time[4];
135 tim.tm_mon = ps2time[5] - 1;
136 tim.tm_year = ((u16)ps2time[6] | ((u16)ps2time[7] << 8)) - 1900;
137 return mktime(&tim);
138}
139
140static mode_t iox_to_posix_mode(unsigned int ps2mode)
141{
142 mode_t posixmode = 0;
143 if (ps2mode & FIO_S_IFREG) posixmode |= S_IFREG;
144 if (ps2mode & FIO_S_IFDIR) posixmode |= S_IFDIR;
145 if (ps2mode & FIO_S_IRUSR) posixmode |= S_IRUSR;
146 if (ps2mode & FIO_S_IWUSR) posixmode |= S_IWUSR;
147 if (ps2mode & FIO_S_IXUSR) posixmode |= S_IXUSR;
148 if (ps2mode & FIO_S_IRGRP) posixmode |= S_IRGRP;
149 if (ps2mode & FIO_S_IWGRP) posixmode |= S_IWGRP;
150 if (ps2mode & FIO_S_IXGRP) posixmode |= S_IXGRP;
151 if (ps2mode & FIO_S_IROTH) posixmode |= S_IROTH;
152 if (ps2mode & FIO_S_IWOTH) posixmode |= S_IWOTH;
153 if (ps2mode & FIO_S_IXOTH) posixmode |= S_IXOTH;
154 return posixmode;
155}
156
157static void fill_stat(struct stat *stat, const iox_stat_t *fiostat)
158{
159 stat->st_dev = 0;
160 stat->st_ino = 0;
161 stat->st_mode = iox_to_posix_mode(fiostat->mode);
162 stat->st_nlink = 0;
163 stat->st_uid = 0;
164 stat->st_gid = 0;
165 stat->st_rdev = 0;
166 stat->st_size = ((off_t)fiostat->hisize << 32) | (off_t)fiostat->size;
167 stat->st_atime = io_to_posix_time(fiostat->atime);
168 stat->st_mtime = io_to_posix_time(fiostat->mtime);
169 stat->st_ctime = io_to_posix_time(fiostat->ctime);
170 stat->st_blksize = 16*1024;
171 stat->st_blocks = stat->st_size / 512;
172}
173
174int __fileXioGetstatHelper(const char *path, struct stat *buf) {
175 iox_stat_t fiostat;
176
177 if (strncmp(path, "tty", 3) == 0 && path[3] >= '0' && path[3] <= '9' && path[4] == ':')
178 {
179 memset(buf, 0, sizeof(struct stat));
180 buf->st_mode = S_IFCHR;
181 return 0;
182 }
183
184 if (fileXioGetStat(path, &fiostat) < 0) {
185 return -ENOENT;
186 }
187
188 fill_stat(buf, &fiostat);
189
190 return 0;
191}
192
193int __fileXioCloseHelper(void *userdata)
194{
195 int rv;
196 int fd;
197
198 fd = __fileXioGetFdHelper(userdata);
199 if (fd < 0)
200 {
201 return fd;
202 }
203
204 rv = fileXioClose(fd);
205 free(userdata);
206 return rv;
207}
208
209int __fileXioDcloseHelper(void *userdata)
210{
211 int rv;
212 int fd;
213
214 fd = __fileXioGetFdHelper(userdata);
215 if (fd < 0)
216 {
217 return fd;
218 }
219
220 rv = fileXioDclose(fd);
221 free(userdata);
222 return rv;
223}
224
225int __fileXioReadHelper(void *userdata, void *buf, int nbytes)
226{
227 int rv;
228 int fd;
229
230 fd = __fileXioGetFdHelper(userdata);
231 if (fd < 0)
232 {
233 return fd;
234 }
235
236 rv = fileXioRead(fd, buf, nbytes);
237 return rv;
238}
239
240int __fileXioLseekHelper(void *userdata, int offset, int whence)
241{
242 int rv;
243 int fd;
244
245 fd = __fileXioGetFdHelper(userdata);
246 if (fd < 0)
247 {
248 return fd;
249 }
250
251 rv = fileXioLseek(fd, offset, whence);
252 return rv;
253}
254
255int64_t __fileXioLseek64Helper(void *userdata, int64_t offset, int whence)
256{
257 int fd;
258
259 fd = __fileXioGetFdHelper(userdata);
260 if (fd < 0)
261 {
262 return fd;
263 }
264
265 return fileXioLseek64(fd, offset, whence);
266}
267
268int __fileXioWriteHelper(void *userdata, const void *buf, int nbytes)
269{
270 int rv;
271 int fd;
272
273 fd = __fileXioGetFdHelper(userdata);
274 if (fd < 0)
275 {
276 return fd;
277 }
278
279 rv = fileXioWrite(fd, buf, nbytes);
280 return rv;
281}
282
283int __fileXioIoctlHelper(void *userdata, int request, void *data)
284{
285 int rv;
286 int fd;
287
288 fd = __fileXioGetFdHelper(userdata);
289 if (fd < 0)
290 {
291 return fd;
292 }
293
294 rv = fileXioIoctl(fd, request, data);
295 return rv;
296}
297
298int __fileXioIoctl2Helper(void *userdata, int request, void *arg, unsigned int arglen, void *buf, unsigned int buflen)
299{
300 int rv;
301 int fd;
302
303 fd = __fileXioGetFdHelper(userdata);
304 if (fd < 0)
305 {
306 return fd;
307 }
308
309 rv = fileXioIoctl2(fd, request, arg, arglen, buf, buflen);
310 return rv;
311}
312
313int __fileXioDreadHelper(void *userdata, struct dirent *dir)
314{
315 int rv;
316 int fd;
317 iox_dirent_t ioxdir;
318
319 // Took from iox_dirent_t
320 #define __MAXNAMLEN 256
321
322 fd = __fileXioGetFdHelper(userdata);
323 if (fd < 0)
324 {
325 return fd;
326 }
327
328 rv = fileXioDread(fd, &ioxdir);
329 if (rv < 0) {
330 return -ENOENT;
331 }
332
333 dir->d_fileno = rv; // TODO: This number should be in theory a unique number per file
334 snprintf(dir->d_name, sizeof(dir->d_name), "%.*s", (int)(sizeof(ioxdir.name) - 1), ioxdir.name);
335 dir->d_reclen = 0;
336 switch (ioxdir.stat.mode & FIO_S_IFMT) {
337 case FIO_S_IFLNK: dir->d_type = DT_LNK; break;
338 case FIO_S_IFDIR: dir->d_type = DT_DIR; break;
339 case FIO_S_IFREG: dir->d_type = DT_REG; break;
340 default: dir->d_type = DT_UNKNOWN; break;
341 }
342
343 return rv;
344}
345
346int __fileXioLseekDirHelper(void *userdata, int offset, int whence)
347{
348 int i;
349 int fd;
350 char *filename;
351 _fxio_file_info_t *finfo;
352 int uid;
353 struct dirent dir;
354
355 fd = __fileXioGetFdHelper(userdata);
356 if (fd < 0)
357 {
358 return fd;
359 }
360
361 filename = __fileXioGetFilenameHelper(userdata);
362
363 if (filename == NULL)
364 {
365 return -EINVAL;
366 }
367
368 if (userdata == NULL)
369 {
370 return -EINVAL;
371 }
372
373 finfo = (_fxio_file_info_t *)userdata;
374
375 if (whence != SEEK_SET)
376 {
377 return -EINVAL;
378 }
379
380 fileXioDclose(fd);
381 uid = fileXioDopen(filename);
382 finfo->fd = uid;
383 for (i = 0; i < offset; i++) {
384 __fileXioDreadHelper(userdata, &dir);
385 }
386
387 return offset;
388}
389
390int __attribute__((weak)) _open(const char *buf, int flags, ...);
391int __attribute__((weak)) _unlink(const char *path);
392int __attribute__((weak)) _rename(const char *old, const char *new_);
393int __attribute__((weak)) mkdir(const char *path, mode_t mode);
394int __attribute__((weak)) rmdir(const char *path);
395int __attribute__((weak)) _stat(const char *path, struct stat *buf);
396int __attribute__((weak)) _fstat(int fd, struct stat *buf);
397ssize_t __attribute__((weak)) readlink(const char *path, char *buf, size_t bufsiz);
398int __attribute__((weak)) symlink(const char *target, const char *linkpath);
399int __attribute__((weak)) _close(int fd);
400int __attribute__((weak)) _read(int fd, void *buf, size_t nbytes);
401off_t __attribute__((weak)) _lseek(int fd, off_t offset, int whence);
402off64_t __attribute__((weak)) lseek64(int fd, off64_t offset, int whence);
403int __attribute__((weak)) _write(int fd, const void *buf, size_t nbytes);
404int __attribute__((weak)) _ioctl(int fd, int request, void *data);
405int __attribute__((weak)) _ps2sdk_ioctl(int fd, int request, void *data);
406int __attribute__((weak)) getdents(int fd, void *dd_buf, int count);
407
408extern void __fileXioOpsInitializeImpl(void)
409{
410 memset(&__fileXio_fdman_path_ops, 0, sizeof(__fileXio_fdman_path_ops));
411 // cppcheck-suppress knownConditionTrueFalse
412 if (&_open) __fileXio_fdman_path_ops.open = __fileXioOpenHelper;
413 // cppcheck-suppress knownConditionTrueFalse
414 if (&_unlink) __fileXio_fdman_path_ops.remove = fileXioRemove;
415 // cppcheck-suppress knownConditionTrueFalse
416 if (&_rename) __fileXio_fdman_path_ops.rename = fileXioRename;
417 // cppcheck-suppress knownConditionTrueFalse
418 if (&mkdir) __fileXio_fdman_path_ops.mkdir = fileXioMkdir;
419 // cppcheck-suppress knownConditionTrueFalse
420 if (&rmdir) __fileXio_fdman_path_ops.rmdir = fileXioRmdir;
421 // cppcheck-suppress knownConditionTrueFalse
422 if ((&_stat) || (&_fstat)) __fileXio_fdman_path_ops.stat = __fileXioGetstatHelper;
423 // cppcheck-suppress knownConditionTrueFalse
424 if (&readlink) __fileXio_fdman_path_ops.readlink = fileXioReadlink;
425 // cppcheck-suppress knownConditionTrueFalse
426 if (&symlink) __fileXio_fdman_path_ops.symlink = fileXioSymlink;
427
428 memset(&__fileXio_fdman_ops_file, 0, sizeof(__fileXio_fdman_ops_file));
429 __fileXio_fdman_ops_file.getfd = __fileXioGetFdHelper;
430 __fileXio_fdman_ops_file.getfilename = __fileXioGetFilenameHelper;
431 // cppcheck-suppress knownConditionTrueFalse
432 if (&_close) __fileXio_fdman_ops_file.close = __fileXioCloseHelper;
433 // cppcheck-suppress knownConditionTrueFalse
434 if (&_read) __fileXio_fdman_ops_file.read = __fileXioReadHelper;
435 // cppcheck-suppress knownConditionTrueFalse
436 if (&_lseek) __fileXio_fdman_ops_file.lseek = __fileXioLseekHelper;
437 // cppcheck-suppress knownConditionTrueFalse
438 if (&lseek64) __fileXio_fdman_ops_file.lseek64 = __fileXioLseek64Helper;
439 // cppcheck-suppress knownConditionTrueFalse
440 if (&_write) __fileXio_fdman_ops_file.write = __fileXioWriteHelper;
441 // cppcheck-suppress knownConditionTrueFalse
442 if ((&_ioctl) || (&_ps2sdk_ioctl)) __fileXio_fdman_ops_file.ioctl = __fileXioIoctlHelper;
443 __fileXio_fdman_ops_file.ioctl2 = __fileXioIoctl2Helper;
444
445 memset(&__fileXio_fdman_ops_dir, 0, sizeof(__fileXio_fdman_ops_dir));
446 __fileXio_fdman_ops_dir.getfd = __fileXioGetFdHelper;
447 __fileXio_fdman_ops_dir.getfilename = __fileXioGetFilenameHelper;
448 // cppcheck-suppress knownConditionTrueFalse
449 if (&_close) __fileXio_fdman_ops_dir.close = __fileXioDcloseHelper;
450 // cppcheck-suppress knownConditionTrueFalse
451 if (&_lseek) __fileXio_fdman_ops_dir.lseek = __fileXioLseekDirHelper;
452 // cppcheck-suppress knownConditionTrueFalse
453 if (&getdents) __fileXio_fdman_ops_dir.dread = __fileXioDreadHelper;
454}
455
456/* Backup pointer functions to restore after exit fileXio */
457static _libcglue_fdman_path_ops_t *_backup_libcglue_fdman_path_ops;
458
459void _ps2sdk_fileXio_init()
460{
461 _backup_libcglue_fdman_path_ops = _libcglue_fdman_path_ops;
462 _libcglue_fdman_path_ops = &__fileXio_fdman_path_ops;
463}
464
465void _ps2sdk_fileXio_deinit()
466{
467 _libcglue_fdman_path_ops = _backup_libcglue_fdman_path_ops;
468}
#define ENOENT
Definition errno.h:32
#define EINVAL
Definition errno.h:72
#define ENOMEM
Definition errno.h:52
#define FIO_S_IFMT
Definition iox_stat.h:40
#define FIO_S_IXGRP
Definition iox_stat.h:72
#define FIO_S_IROTH
Definition iox_stat.h:77
#define FIO_S_IXUSR
Definition iox_stat.h:63
#define FIO_S_IRGRP
Definition iox_stat.h:68
#define FIO_S_IXOTH
Definition iox_stat.h:81
#define FIO_S_IWOTH
Definition iox_stat.h:79
#define FIO_S_IRUSR
Definition iox_stat.h:59
#define FIO_S_IWGRP
Definition iox_stat.h:70
#define FIO_S_IFLNK
Definition iox_stat.h:42
#define FIO_S_IFDIR
Definition iox_stat.h:46
#define FIO_S_IFREG
Definition iox_stat.h:44
#define FIO_S_IWUSR
Definition iox_stat.h:61
u32 count
start sector of fragmented bd/file