PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
ps2sdkapi.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 "iox_stat.h"
26
27typedef struct _fio_file_info_
28{
29 // cppcheck-suppress unusedStructMember
30 int fd;
31 // cppcheck-suppress unusedStructMember
32 char filename[];
34
35#ifdef F___fioOpsInitialize
36_libcglue_fdman_path_ops_t __fio_fdman_path_ops;
37_libcglue_fdman_fd_ops_t __fio_fdman_ops_file;
38_libcglue_fdman_fd_ops_t __fio_fdman_ops_dir;
39
40extern void __fioOpsInitializeImpl(void);
41
42__attribute__((constructor))
43static void __fioOpsInitialize(void)
44{
45 __fioOpsInitializeImpl();
46}
47#else
48extern _libcglue_fdman_path_ops_t __fio_fdman_path_ops;
49extern _libcglue_fdman_fd_ops_t __fio_fdman_ops_file;
50extern _libcglue_fdman_fd_ops_t __fio_fdman_ops_dir;
51#endif
52
53#ifdef F___fioOpenHelper
54#define IOP_O_RDONLY 0x0001
55#define IOP_O_WRONLY 0x0002
56#define IOP_O_RDWR 0x0003
57#define IOP_O_DIROPEN 0x0008 // Internal use for dopen
58#define IOP_O_NBLOCK 0x0010
59#define IOP_O_APPEND 0x0100
60#define IOP_O_CREAT 0x0200
61#define IOP_O_TRUNC 0x0400
62#define IOP_O_EXCL 0x0800
63#define IOP_O_NOWAIT 0x8000
64
65int __fioOpenHelper(_libcglue_fdman_fd_info_t *info, const char *buf, int flags, mode_t mode)
66{
67 int iop_flags = 0;
68 int is_dir = 0;
69 int iop_fd;
70
71 // newlib flags differ from iop flags
72 if ((flags & 3) == O_RDONLY) iop_flags |= IOP_O_RDONLY;
73 if ((flags & 3) == O_WRONLY) iop_flags |= IOP_O_WRONLY;
74 if ((flags & 3) == O_RDWR ) iop_flags |= IOP_O_RDWR;
75 if (flags & O_NONBLOCK) iop_flags |= IOP_O_NBLOCK;
76 if (flags & O_APPEND) iop_flags |= IOP_O_APPEND;
77 if (flags & O_CREAT) iop_flags |= IOP_O_CREAT;
78 if (flags & O_TRUNC) iop_flags |= IOP_O_TRUNC;
79 if (flags & O_EXCL) iop_flags |= IOP_O_EXCL;
80 //if (flags & O_???) iop_flags |= IOP_O_NOWAIT;
81 if (flags & O_DIRECTORY) {
82 iop_flags |= IOP_O_DIROPEN;
83 is_dir = 1;
84 }
85
86 iop_fd = is_dir ? fioDopen(buf) : fioOpen(buf, iop_flags);
87 if (iop_fd >= 0) {
88 _fio_file_info_t *userdata;
89 int buf_len;
90
91 buf_len = strlen(buf);
92 userdata = malloc(sizeof(_fio_file_info_t) + buf_len + 1);
93 if (userdata == NULL)
94 {
95 return -ENOMEM;
96 }
97 userdata->fd = iop_fd;
98 memcpy(userdata->filename, buf, buf_len);
99 userdata->filename[buf_len] = '\x00';
100 info->userdata = (void *)userdata;
101 info->ops = is_dir ? &__fio_fdman_ops_dir : &__fio_fdman_ops_file;
102 return 0;
103 }
104 return iop_fd;
105}
106#else
107int __fioOpenHelper(_libcglue_fdman_fd_info_t *info, const char *buf, int flags, mode_t mode);
108#endif
109
110#ifdef F___fioGetFdHelper
111int __fioGetFdHelper(void *userdata)
112{
113 _fio_file_info_t *finfo;
114
115 if (userdata == NULL)
116 {
117 return -EINVAL;
118 }
119
120 finfo = (_fio_file_info_t *)userdata;
121 return finfo->fd;
122}
123#else
124int __fioGetFdHelper(void *userdata);
125#endif
126
127#ifdef F___fioGetFilenameHelper
128char *__fioGetFilenameHelper(void *userdata)
129{
130 _fio_file_info_t *finfo;
131
132 if (userdata == NULL)
133 {
134 return NULL;
135 }
136
137 finfo = (_fio_file_info_t *)userdata;
138 return finfo->filename;
139}
140#else
141char *__fioGetFilenameHelper(void *userdata);
142#endif
143
144#ifdef F___fioCloseHelper
145int __fioCloseHelper(void *userdata)
146{
147 int rv;
148 int fd;
149
150 fd = __fioGetFdHelper(userdata);
151 if (fd < 0)
152 {
153 return fd;
154 }
155
156 rv = fioClose(fd);
157 free(userdata);
158 return rv;
159}
160#else
161int __fioCloseHelper(void *userdata);
162#endif
163
164#ifdef F___fioDcloseHelper
165int __fioDcloseHelper(void *userdata)
166{
167 int rv;
168 int fd;
169
170 fd = __fioGetFdHelper(userdata);
171 if (fd < 0)
172 {
173 return fd;
174 }
175
176 rv = fioDclose(fd);
177 free(userdata);
178 return rv;
179}
180#else
181int __fioDcloseHelper(void *userdata);
182#endif
183
184#ifdef F___fioReadHelper
185int __fioReadHelper(void *userdata, void *buf, int nbytes)
186{
187 int rv;
188 int fd;
189
190 fd = __fioGetFdHelper(userdata);
191 if (fd < 0)
192 {
193 return fd;
194 }
195
196 rv = fioRead(fd, buf, nbytes);
197 return rv;
198}
199#else
200int __fioReadHelper(void *userdata, void *buf, int nbytes);
201#endif
202
203#ifdef F___fioLseekHelper
204int __fioLseekHelper(void *userdata, int offset, int whence)
205{
206 int rv;
207 int fd;
208
209 fd = __fioGetFdHelper(userdata);
210 if (fd < 0)
211 {
212 return fd;
213 }
214
215 rv = fioLseek(fd, offset, whence);
216 return rv;
217}
218#else
219int __fioLseekHelper(void *userdata, int offset, int whence);
220#endif
221
222#ifdef F___fioWriteHelper
223int __fioWriteHelper(void *userdata, const void *buf, int nbytes)
224{
225 int rv;
226 int fd;
227
228 fd = __fioGetFdHelper(userdata);
229 if (fd < 0)
230 {
231 return fd;
232 }
233
234 rv = fioWrite(fd, buf, nbytes);
235 return rv;
236}
237#else
238int __fioWriteHelper(void *userdata, const void *buf, int nbytes);
239#endif
240
241#ifdef F___fioIoctlHelper
242int __fioIoctlHelper(void *userdata, int request, void *data)
243{
244 int rv;
245 int fd;
246
247 fd = __fioGetFdHelper(userdata);
248 if (fd < 0)
249 {
250 return fd;
251 }
252
253 rv = fioIoctl(fd, request, data);
254 return rv;
255}
256#else
257int __fioIoctlHelper(void *userdata, int request, void *data);
258#endif
259
260#ifdef F___fioDreadHelper
261int __fioDreadHelper(void *userdata, struct dirent *dir)
262{
263 int rv;
264 int fd;
265 io_dirent_t iodir;
266
267 // Took from io_dirent_t
268 #define __MAXNAMLEN 256
269
270 fd = __fioGetFdHelper(userdata);
271 if (fd < 0)
272 {
273 return fd;
274 }
275
276 rv = fioDread(fd, &iodir);
277 if (rv < 0) {
278 errno = ENOENT;
279 return -1;
280 }
281
282 dir->d_fileno = rv; // TODO: This number should be in theory a unique number per file
283 strncpy(dir->d_name, iodir.name, __MAXNAMLEN);
284 dir->d_name[__MAXNAMLEN - 1] = 0;
285 dir->d_reclen = 0;
286 switch (iodir.stat.mode & FIO_SO_IFMT) {
287 case FIO_SO_IFLNK: dir->d_type = DT_LNK; break;
288 case FIO_SO_IFDIR: dir->d_type = DT_DIR; break;
289 case FIO_SO_IFREG: dir->d_type = DT_REG; break;
290 default: dir->d_type = DT_UNKNOWN; break;
291 }
292
293
294 return rv;
295}
296#else
297int __fioDreadHelper(void *userdata, struct dirent *dir);
298#endif
299
300#ifdef F___fioLseekDirHelper
301int __fioLseekDirHelper(void *userdata, int offset, int whence)
302{
303 int i;
304 int fd;
305 char *filename;
306 _fio_file_info_t *finfo;
307 int uid;
308 struct dirent dir;
309
310 fd = __fioGetFdHelper(userdata);
311 if (fd < 0)
312 {
313 return fd;
314 }
315
316 filename = __fioGetFilenameHelper(userdata);
317
318 if (filename == NULL)
319 {
320 return -EINVAL;
321 }
322
323 if (userdata == NULL)
324 {
325 return -EINVAL;
326 }
327
328 finfo = (_fio_file_info_t *)userdata;
329
330 if (whence != SEEK_SET)
331 {
332 return -EINVAL;
333 }
334
335 fioDclose(fd);
336 uid = fioDopen(filename);
337 finfo->fd = uid;
338 for (i = 0; i < offset; i++) {
339 __fioDreadHelper(userdata, &dir);
340 }
341
342 return offset;
343}
344#else
345int __fioLseekDirHelper(void *userdata, int offset, int whence);
346#endif
347
348#ifdef F___libcglue_init_stdio
349int __libcglue_init_stdio(_libcglue_fdman_fd_info_t *info, int fd)
350{
351 _fio_file_info_t *userdata;
352 int fnlen;
353 const char *tty0_str = "tty0:";
354
355 fnlen = strlen(tty0_str) + 1;
356
357 userdata = malloc(sizeof(_fio_file_info_t) + fnlen);
358 if (userdata == NULL)
359 {
360 return -ENOMEM;
361 }
362 userdata->fd = fd;
363 memcpy(userdata->filename, tty0_str, fnlen - 1);
364 userdata->filename[fnlen - 1] = '\x00';
365 info->userdata = (void *)userdata;
366 info->ops = &__fio_fdman_ops_file;
367 return 0;
368}
369#endif
370
372#ifdef F___fioMkdirHelper
373int __fioMkdirHelper(const char *path, int mode)
374{
375 // Old fio mkdir has no mode argument
376 (void)mode;
377
378 return fioMkdir(path);
379}
380#else
381int __fioMkdirHelper(const char *path, int mode);
382#endif
383
384#ifdef F___fioGetstatHelper
385static time_t io_to_posix_time(const unsigned char *ps2time)
386{
387 struct tm tim;
388 tim.tm_sec = ps2time[1];
389 tim.tm_min = ps2time[2];
390 tim.tm_hour = ps2time[3];
391 tim.tm_mday = ps2time[4];
392 tim.tm_mon = ps2time[5] - 1;
393 tim.tm_year = ((u16)ps2time[6] | ((u16)ps2time[7] << 8)) - 1900;
394 return mktime(&tim);
395}
396
397static mode_t io_to_posix_mode(unsigned int ps2mode)
398{
399 mode_t posixmode = 0;
400 if (ps2mode & FIO_SO_IFREG) posixmode |= S_IFREG;
401 if (ps2mode & FIO_SO_IFDIR) posixmode |= S_IFDIR;
402 if (ps2mode & FIO_SO_IROTH) posixmode |= S_IRUSR|S_IRGRP|S_IROTH;
403 if (ps2mode & FIO_SO_IWOTH) posixmode |= S_IWUSR|S_IWGRP|S_IWOTH;
404 if (ps2mode & FIO_SO_IXOTH) posixmode |= S_IXUSR|S_IXGRP|S_IXOTH;
405 return posixmode;
406}
407
408static void __fill_stat(struct stat *stat, const io_stat_t *fiostat)
409{
410 stat->st_dev = 0;
411 stat->st_ino = 0;
412 stat->st_mode = io_to_posix_mode(fiostat->mode);
413 stat->st_nlink = 0;
414 stat->st_uid = 0;
415 stat->st_gid = 0;
416 stat->st_rdev = 0;
417 stat->st_size = ((off_t)fiostat->hisize << 32) | (off_t)fiostat->size;
418 stat->st_atime = io_to_posix_time(fiostat->atime);
419 stat->st_mtime = io_to_posix_time(fiostat->mtime);
420 stat->st_ctime = io_to_posix_time(fiostat->ctime);
421 stat->st_blksize = 16*1024;
422 stat->st_blocks = stat->st_size / 512;
423}
424
425int __fioGetstatHelper(const char *path, struct stat *buf)
426{
427 io_stat_t fiostat;
428
429 if (strncmp(path, "tty", 3) == 0 && path[3] >= '0' && path[3] <= '9' && path[4] == ':')
430 {
431 memset(buf, 0, sizeof(struct stat));
432 buf->st_mode = S_IFCHR;
433 return 0;
434 }
435
436 if (fioGetstat(path, &fiostat) < 0) {
437 errno = ENOENT;
438 return -1;
439 }
440
441 __fill_stat(buf, &fiostat);
442
443 return 0;
444}
445#else
446int __fioGetstatHelper(const char *path, struct stat *buf);
447#endif
448
449#ifdef F___fioOpsInitializeImpl
450int __attribute__((weak)) _open(const char *buf, int flags, ...);
451int __attribute__((weak)) _unlink(const char *path);
452int __attribute__((weak)) mkdir(const char *path, mode_t mode);
453int __attribute__((weak)) rmdir(const char *path);
454int __attribute__((weak)) _stat(const char *path, struct stat *buf);
455int __attribute__((weak)) _fstat(int fd, struct stat *buf);
456int __attribute__((weak)) _close(int fd);
457int __attribute__((weak)) _read(int fd, void *buf, size_t nbytes);
458off_t __attribute__((weak)) _lseek(int fd, off_t offset, int whence);
459int __attribute__((weak)) _write(int fd, const void *buf, size_t nbytes);
460int __attribute__((weak)) _ioctl(int fd, int request, void *data);
461int __attribute__((weak)) getdents(int fd, void *dd_buf, int count);
462
463void __fioOpsInitializeImpl(void)
464{
465 memset(&__fio_fdman_path_ops, 0, sizeof(__fio_fdman_path_ops));
466 // cppcheck-suppress knownConditionTrueFalse
467 if (&_open) __fio_fdman_path_ops.open = __fioOpenHelper;
468 // cppcheck-suppress knownConditionTrueFalse
469 if (&_unlink) __fio_fdman_path_ops.remove = fioRemove;
470 // cppcheck-suppress knownConditionTrueFalse
471 if (&mkdir) __fio_fdman_path_ops.mkdir = __fioMkdirHelper;
472 // cppcheck-suppress knownConditionTrueFalse
473 if (&rmdir) __fio_fdman_path_ops.rmdir = fioRmdir;
474 // cppcheck-suppress knownConditionTrueFalse
475 if ((&_stat) || (&_fstat)) __fio_fdman_path_ops.stat = __fioGetstatHelper;
476
477 memset(&__fio_fdman_ops_file, 0, sizeof(__fio_fdman_ops_file));
478 __fio_fdman_ops_file.getfd = __fioGetFdHelper;
479 __fio_fdman_ops_file.getfilename = __fioGetFilenameHelper;
480 // cppcheck-suppress knownConditionTrueFalse
481 if (&_close) __fio_fdman_ops_file.close = __fioCloseHelper;
482 // cppcheck-suppress knownConditionTrueFalse
483 if (&_read) __fio_fdman_ops_file.read = __fioReadHelper;
484 // cppcheck-suppress knownConditionTrueFalse
485 if (&_lseek) __fio_fdman_ops_file.lseek = __fioLseekHelper;
486 // cppcheck-suppress knownConditionTrueFalse
487 if (&_write) __fio_fdman_ops_file.write = __fioWriteHelper;
488 // cppcheck-suppress knownConditionTrueFalse
489 if (&_ioctl) __fio_fdman_ops_file.ioctl = __fioIoctlHelper;
490
491 memset(&__fio_fdman_ops_dir, 0, sizeof(__fio_fdman_ops_dir));
492 __fio_fdman_ops_dir.getfd = __fioGetFdHelper;
493 __fio_fdman_ops_dir.getfilename = __fioGetFilenameHelper;
494 // cppcheck-suppress knownConditionTrueFalse
495 if (&_close) __fio_fdman_ops_dir.close = __fioDcloseHelper;
496 // cppcheck-suppress knownConditionTrueFalse
497 if (&_lseek) __fio_fdman_ops_dir.lseek = __fioLseekDirHelper;
498 // cppcheck-suppress knownConditionTrueFalse
499 if (&getdents) __fio_fdman_ops_dir.dread = __fioDreadHelper;
500}
501#endif
502
503#ifdef F__libcglue_fdman_path_ops
504_libcglue_fdman_path_ops_t *_libcglue_fdman_path_ops = &__fio_fdman_path_ops;
505#endif
506
507#ifdef F__libcglue_fdman_socket_ops
508_libcglue_fdman_socket_ops_t *_libcglue_fdman_socket_ops = NULL;
509#endif
510
511#ifdef F__libcglue_fdman_inet_ops
512_libcglue_fdman_inet_ops_t *_libcglue_fdman_inet_ops = NULL;
513#endif
#define ENOENT
Definition errno.h:23
#define EINVAL
Definition errno.h:63
#define ENOMEM
Definition errno.h:43
#define FIO_SO_IFMT
Definition iox_stat.h:122
#define FIO_SO_IFDIR
Definition iox_stat.h:128
#define FIO_SO_IFLNK
Definition iox_stat.h:124
#define FIO_SO_IXOTH
Definition iox_stat.h:135
#define FIO_SO_IWOTH
Definition iox_stat.h:133
#define FIO_SO_IFREG
Definition iox_stat.h:126
#define FIO_SO_IROTH
Definition iox_stat.h:131
int __fioMkdirHelper(const char *path, int mode)
u32 count
start sector of fragmented bd/file