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