PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
glue.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright 2001-2004, ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <stdarg.h>
14#include <errno.h>
15#include <string.h>
16#include <kernel.h>
17#include <timer.h>
18#include <stdlib.h>
19#include <stdarg.h>
20#include <sio.h>
21
22#include <pwd.h>
23#include <time.h>
24#include <sys/time.h>
25#include <sys/timeb.h>
26#include <sys/times.h>
27#include <sys/utime.h>
28#include <sys/stat.h>
29#include <sys/types.h>
30#include <sys/random.h>
31
32// Include all integer types for compile time checking of:
33// - compiler (gcc)
34// - libc (newlib)
35#include <stdint.h>
36#include <limits.h>
37#include <inttypes.h>
38#include <tamtypes.h>
39
40#define NEWLIB_PORT_AWARE
41#include "io_common.h"
42#include "ps2sdkapi.h"
43#include "timer_alarm.h"
44#include "fdman.h"
45
46/* Functions from cwd.c */
47extern char __cwd[MAXNAMLEN + 1];
48extern size_t __cwd_len;
49int __path_absolute(const char *in, char *out, int len);
50
51extern void * _end;
52
53#ifdef F___dummy_passwd
54/* the present working directory variable. */
55struct passwd __dummy_passwd = { "ps2_user", "xxx", 1000, 1000, "", "", "/", "" };
56#else
57extern struct passwd __dummy_passwd;
58#endif
59
60#ifdef F___transform_errno
61int __transform_errno(int res) {
62 /* On error, -1 is returned and errno is set to indicate the error. */
63 if (res < 0) {
64 errno = -res;
65 return -1;
66 }
67 return res;
68}
69#else
70int __transform_errno(int res);
71#endif
72
73#ifdef F___transform64_errno
74int64_t __transform64_errno(int64_t res) {
75 /* On error, -1 is returned and errno is set to indicate the error. */
76 if (res < 0) {
77 errno = -res;
78 return -1;
79 }
80 return res;
81}
82#else
83int64_t __transform64_errno(int64_t res);
84#endif
85
86#if INT_MAX != 0x7fffffffL
87 #error "INT_MAX != 0x7fffffffL"
88#endif
89#ifndef LONG_MAX
90 #error "LONG_MAX not defined"
91#endif
92#if LONG_MAX != 0x7fffffffL
93 #error "LONG_MAX != 0x7fffffffL"
94#endif
95
96#define ct_assert(e) {enum { ct_assert_value = 1/(!!(e)) };}
97#ifdef F_compile_time_check
98void compile_time_check() {
99 // Compiler (ABI n32)
100 ct_assert(sizeof(unsigned char)==1);
101 ct_assert(sizeof(unsigned short)==2);
102 ct_assert(sizeof(unsigned int)==4);
103 ct_assert(sizeof(unsigned long)==4);
104 ct_assert(sizeof(unsigned long long)==8);
105 ct_assert(sizeof(unsigned int __attribute__(( mode(TI) )))==16);
106 ct_assert(sizeof(void *)==4);
107
108 // Defined in tamtypes.h (ps2sdk)
109 ct_assert(sizeof(u8)==1);
110 ct_assert(sizeof(u16)==2);
111 ct_assert(sizeof(u32)==4);
112 ct_assert(sizeof(u64)==8);
113 ct_assert(sizeof(u128)==16);
114
115 // Defined in inttypes.h/stdint.h (newlib)
116 ct_assert(sizeof(uint8_t)==1);
117 ct_assert(sizeof(uint16_t)==2);
118 ct_assert(sizeof(uint32_t)==4);
119 ct_assert(sizeof(uint64_t)==8);
120}
121#endif
122
123#ifdef F__open
124int _open(const char *buf, int flags, ...) {
125 int iop_fd, fd;
126 int mode;
128 va_list alist;
129 char t_fname[MAXNAMLEN + 1];
130
131 va_start(alist, flags);
132 mode = va_arg(alist, int); // Retrieve the mode argument, regardless of whether it is expected or not.
133 va_end(alist);
134
135 if(__path_absolute(buf, t_fname, MAXNAMLEN) < 0) {
136 errno = ENAMETOOLONG;
137 return -1;
138 }
139
140 if (_libcglue_fdman_path_ops == NULL || _libcglue_fdman_path_ops->open == NULL)
141 {
142 errno = ENOSYS;
143 return -1;
144 }
145
146 fd = __fdman_get_new_descriptor();
147 if (fd == -1)
148 {
149 errno = ENOMEM;
150 return -1;
151 }
152
153 info = &(__descriptormap[fd]->info);
154 iop_fd = _libcglue_fdman_path_ops->open(info, t_fname, flags, mode);
155 if (iop_fd < 0)
156 {
157 __fdman_release_descriptor(fd);
158 return __transform_errno(iop_fd);
159 }
160 __descriptormap[fd]->flags = flags;
161 return fd;
162}
163#endif
164
165#ifdef F__close
166int _close(int fd) {
167 int ret = 0;
168
169 if (!__IS_FD_VALID(fd)) {
170 errno = EBADF;
171 return -1;
172 }
173
174 if (__descriptormap[fd]->ref_count == 1)
175 {
177
178 fdinfo = &(__descriptormap[fd]->info);
179 if (fdinfo->ops != NULL && fdinfo->ops->close != NULL)
180 {
181 ret = __transform_errno(fdinfo->ops->close(fdinfo->userdata));
182 }
183 }
184 __fdman_release_descriptor(fd);
185 return ret;
186}
187#endif
188
189#ifdef F__read
190int _read(int fd, void *buf, size_t nbytes) {
191 if (!__IS_FD_VALID(fd)) {
192 errno = EBADF;
193 return -1;
194 }
195
197
198 fdinfo = &(__descriptormap[fd]->info);
199 if (fdinfo->ops == NULL || fdinfo->ops->read == NULL)
200 {
201 errno = ENOSYS;
202 return -1;
203 }
204 return __transform_errno(fdinfo->ops->read(fdinfo->userdata, buf, nbytes));
205}
206#endif
207
208#ifdef F__write
209int _write(int fd, const void *buf, size_t nbytes) {
210 if (!__IS_FD_VALID(fd)) {
211 errno = EBADF;
212 return -1;
213 }
214
216
217 fdinfo = &(__descriptormap[fd]->info);
218 if (fdinfo->ops == NULL || fdinfo->ops->write == NULL)
219 {
220 errno = ENOSYS;
221 return -1;
222 }
223 return __transform_errno(fdinfo->ops->write(fdinfo->userdata, buf, nbytes));
224}
225#endif
226
227#ifdef F__stat
228int _stat(const char *path, struct stat *buf) {
229 char dest[MAXNAMLEN + 1];
230
231 if(__path_absolute(path, dest, MAXNAMLEN) < 0) {
232 errno = ENAMETOOLONG;
233 return -1;
234 }
235
236 if (_libcglue_fdman_path_ops == NULL || _libcglue_fdman_path_ops->stat == NULL)
237 {
238 errno = ENOSYS;
239 return -1;
240 }
241
242 return __transform_errno(_libcglue_fdman_path_ops->stat(dest, buf));
243}
244#endif
245
246#ifdef F_lstat
247int lstat(const char *path, struct stat *buf) {
248 return stat(path, buf);
249}
250#endif
251
252#ifdef F__fstat
253int _fstat(int fd, struct stat *buf) {
254 if (!__IS_FD_VALID(fd)) {
255 errno = EBADF;
256 return -1;
257 }
258
260 char *filename;
261
262 fdinfo = &(__descriptormap[fd]->info);
263 if (fdinfo->ops == NULL || fdinfo->ops->getfilename == NULL)
264 {
265 errno = ENOSYS;
266 return -1;
267 }
268 filename = fdinfo->ops->getfilename(fdinfo->userdata);
269 if (filename == NULL)
270 {
271 errno = ENOENT;
272 return -1;
273 }
274
275 if (_libcglue_fdman_path_ops == NULL || _libcglue_fdman_path_ops->stat == NULL)
276 {
277 errno = ENOSYS;
278 return -1;
279 }
280
281 return __transform_errno(_libcglue_fdman_path_ops->stat(filename, buf));
282}
283#endif
284
285#ifdef F_access
286int access(const char *fn, int flags) {
287 struct stat s;
288 if (stat(fn, &s))
289 return -1;
290 if (s.st_mode & S_IFDIR)
291 return 0;
292 if (flags & W_OK) {
293 if (s.st_mode & S_IWRITE)
294 return 0;
295 errno = EACCES;
296 return -1;
297 }
298 return 0;
299}
300#endif
301
302#ifdef F__fcntl
303int _fcntl(int fd, int cmd, ...)
304{
305 if (!__IS_FD_VALID(fd)) {
306 errno = EBADF;
307 return -1;
308 }
309
310 switch (cmd)
311 {
312 case F_DUPFD:
313 {
314 return __fdman_get_dup_descriptor(fd);
315 break;
316 }
317 case F_GETFL:
318 {
319 return __descriptormap[fd]->flags;
320 break;
321 }
322 case F_SETFL:
323 {
324 int newfl, rv;
325 va_list args;
326
327 rv = 0;
328
329 va_start (args, cmd); /* Initialize the argument list. */
330 newfl = va_arg(args, int);
331 va_end (args); /* Clean up. */
332
333 __descriptormap[fd]->flags = newfl;
334
335 {
337
338 fdinfo = &(__descriptormap[fd]->info);
339
340 if (fdinfo->ops != NULL && fdinfo->ops->fcntl_f_setfl != NULL)
341 {
342 rv = __transform_errno(fdinfo->ops->fcntl_f_setfl(fdinfo->userdata, newfl));
343 }
344 }
345 return rv;
346 }
347 case F_SETFD:
348 {
349 int newfl;
350 va_list args;
351
352 va_start (args, cmd); /* Initialize the argument list. */
353 newfl = va_arg(args, int);
354 va_end (args); /* Clean up. */
355
356 __descriptormap[fd]->flags = newfl;
357 return 0;
358 break;
359 }
360 }
361
362 errno = EBADF;
363 return -1;
364}
365#endif /* F__fcntl */
366
367#ifdef F_getdents
368int getdents(int fd, void *dd_buf, int count)
369{
370 struct dirent *dirp;
371 int rv, read;
372
373 read = 0;
374 dirp = (struct dirent *)dd_buf;
375
376 {
378
379 fdinfo = &(__descriptormap[fd]->info);
380 rv = -ENOSYS;
381 if (fdinfo->ops != NULL && fdinfo->ops->dread != NULL)
382 {
383 rv = __transform_errno(fdinfo->ops->dread(fdinfo->userdata, dirp));
384 }
385 }
386 if (rv < 0) {
387 return __transform_errno(rv);
388 } else if (rv == 0) {
389 return read;
390 }
391
392 read += sizeof(struct dirent);
393 dirp->d_reclen = count;
394
395 return read;
396}
397#endif
398
399
400
401#ifdef F__lseek
402off_t _lseek(int fd, off_t offset, int whence)
403{
404 if (!__IS_FD_VALID(fd)) {
405 errno = EBADF;
406 return -1;
407 }
408
410
411 fdinfo = &(__descriptormap[fd]->info);
412 if (fdinfo->ops == NULL || fdinfo->ops->lseek == NULL)
413 {
414 errno = ENOSYS;
415 return -1;
416 }
417 return __transform_errno(fdinfo->ops->lseek(fdinfo->userdata, offset, whence));
418}
419#endif
420
421#ifdef F_lseek64
422off64_t lseek64(int fd, off64_t offset, int whence)
423{
424 if (!__IS_FD_VALID(fd)) {
425 errno = EBADF;
426 return -1;
427 }
428
430
431 fdinfo = &(__descriptormap[fd]->info);
432 if (fdinfo->ops == NULL || fdinfo->ops->lseek64 == NULL)
433 {
434 errno = ENOSYS;
435 return -1;
436 }
437 return __transform64_errno(fdinfo->ops->lseek64(fdinfo->userdata, offset, whence));
438}
439#endif
440
441#ifdef F_chdir
442int chdir(const char *path) {
443 char dest[MAXNAMLEN + 1];
444
445 if(__path_absolute(path, dest, MAXNAMLEN) < 0) {
446 errno = ENAMETOOLONG;
447 return -1;
448 }
449
450 strncpy(__cwd, dest, sizeof(__cwd));
451 __cwd_len = strnlen(__cwd, sizeof(__cwd));
452 return 0;
453}
454#endif
455
456#ifdef F_mkdir
457int mkdir(const char *path, mode_t mode) {
458 char dest[MAXNAMLEN + 1];
459
460 if(__path_absolute(path, dest, MAXNAMLEN) < 0) {
461 errno = ENAMETOOLONG;
462 return -1;
463 }
464
465 if (_libcglue_fdman_path_ops == NULL || _libcglue_fdman_path_ops->mkdir == NULL)
466 {
467 errno = ENOSYS;
468 return -1;
469 }
470
471 return __transform_errno(_libcglue_fdman_path_ops->mkdir(dest, mode));
472}
473#endif
474
475#ifdef F_rmdir
476int rmdir(const char *path) {
477 char dest[MAXNAMLEN + 1];
478
479 if(__path_absolute(path, dest, MAXNAMLEN) < 0) {
480 errno = ENAMETOOLONG;
481 return -1;
482 }
483
484 if (_libcglue_fdman_path_ops == NULL || _libcglue_fdman_path_ops->rmdir == NULL)
485 {
486 errno = ENOSYS;
487 return -1;
488 }
489
490 return __transform_errno(_libcglue_fdman_path_ops->rmdir(dest));
491}
492#endif
493
494#ifdef F__link
495int _link(const char *old, const char *new) {
496 errno = ENOSYS;
497 return -1; /* not supported */
498}
499#endif
500
501#ifdef F__unlink
502int _unlink(const char *path) {
503 char dest[MAXNAMLEN + 1];
504 if(__path_absolute(path, dest, MAXNAMLEN) < 0) {
505 errno = ENAMETOOLONG;
506 return -1;
507 }
508
509 if (_libcglue_fdman_path_ops == NULL || _libcglue_fdman_path_ops->remove == NULL)
510 {
511 errno = ENOSYS;
512 return -1;
513 }
514
515 return __transform_errno(_libcglue_fdman_path_ops->remove(dest));
516}
517#endif
518
519#ifdef F__rename
520int _rename(const char *old, const char *new) {
521 char oldname[MAXNAMLEN + 1];
522 char newname[MAXNAMLEN + 1];
523
524 if(__path_absolute(old, oldname, MAXNAMLEN) < 0) {
525 errno = ENAMETOOLONG;
526 return -1;
527 }
528
529 if(__path_absolute(new, newname, MAXNAMLEN) < 0) {
530 errno = ENAMETOOLONG;
531 return -1;
532 }
533
534 if (_libcglue_fdman_path_ops == NULL || _libcglue_fdman_path_ops->rename == NULL)
535 {
536 errno = ENOSYS;
537 return -1;
538 }
539
540 return __transform_errno(_libcglue_fdman_path_ops->rename(oldname, newname));
541}
542#endif
543
544#ifdef F__getpid
545int _getpid(void) {
546 return GetThreadId();
547}
548#endif
549
550#ifdef F__kill
551int _kill(int pid, int sig) {
552#if 0 // needs to be tested first
553 // null signal: do error checking on pid only
554 if (sig == 0)
555 return pid == getpid() ? 0 : -1;
556
557 if (pid == getpid()) {
558 ExitDeleteThread();
559 // NOTE: ExitDeleteThread does not return
560 return 0;
561 }
562#endif
563 (void)pid;
564 (void)sig;
565 errno = ENOSYS;
566 return 1; /* not supported */
567}
568#endif
569
570#ifdef F__fork
571pid_t _fork(void) {
572 errno = ENOSYS;
573 return (pid_t) -1; /* not supported */
574}
575#endif
576
577#ifdef F__wait
578pid_t _wait(int *unused) {
579 errno = ENOSYS;
580 return (pid_t) -1; /* not supported */
581}
582#endif
583
584#ifdef F__execve
585int _execve(const char *name, char *const argv[], char *const env[]) {
586 errno = ENOSYS;
587 return (pid_t) -1; /* not supported */
588}
589#endif
590
591#ifdef F__sbrk
592void * _sbrk(size_t incr) {
593 static void * _heap_ptr = &_end;
594 void *mp, *ret = (void *)-1;
595
596 if (incr == 0)
597 return _heap_ptr;
598
599 /* If the area we want to allocated is past the end of our heap, we have a problem. */
600 mp = _heap_ptr + incr;
601 if (mp <= EndOfHeap()) {
602 ret = _heap_ptr;
603 _heap_ptr = mp;
604 }
605
606 return ret;
607}
608#endif
609
610#ifdef F__gettimeofday
611int _gettimeofday(struct timeval *tv, struct timezone *tz)
612{
613 if (tv == NULL)
614 {
615 errno = EFAULT;
616 return -1;
617 }
618
619 {
620 u32 busclock_sec;
621 u32 busclock_usec;
622
623 TimerBusClock2USec(GetTimerSystemTime(), &busclock_sec, &busclock_usec);
624 tv->tv_sec = (time_t)(_ps2sdk_rtc_offset_from_busclk + ((s64)busclock_sec));
625 tv->tv_usec = busclock_usec;
626 }
627
628 if (tz != NULL)
629 {
630 tz->tz_minuteswest = _timezone / 60;
631 tz->tz_dsttime = 0;
632 }
633
634 return 0;
635}
636#endif
637
638#ifdef F__times
639clock_t _times(struct tms *buffer) {
640 clock_t clk = GetTimerSystemTime() / (kBUSCLK / (1000 * 1000));
641
642 if (buffer != NULL) {
643 buffer->tms_utime = clk;
644 buffer->tms_stime = 0;
645 buffer->tms_cutime = 0;
646 buffer->tms_cstime = 0;
647 }
648
649 return clk;
650}
651#endif
652
653#ifdef F_ftime
654int ftime(struct timeb *tb) {
655 struct timeval tv;
656 struct timezone tz;
657
658 gettimeofday(&tv, &tz);
659
660 tb->time = tv.tv_sec;
661 tb->millitm = tv.tv_usec / 1000;
662 tb->timezone = tz.tz_minuteswest;
663 tb->dstflag = tz.tz_dsttime;
664
665 return 0;
666}
667#endif
668
669#ifdef F_clock_getres
670int clock_getres(clockid_t clk_id, struct timespec *res) {
671 struct timeval tv;
672 int ret;
673
674 ret = gettimeofday(&tv, NULL);
675
676 /* Return the actual time since epoch */
677 res->tv_sec = tv.tv_sec;
678 res->tv_nsec = tv.tv_usec * 1000;
679
680 return ret;
681}
682#endif
683
684#ifdef F_clock_gettime
685int clock_gettime(clockid_t clk_id, struct timespec *tp) {
686 struct timeval tv;
687 int res;
688
689 res = gettimeofday(&tv, NULL);
690
691 /* Return the actual time since epoch */
692 tp->tv_sec = tv.tv_sec;
693 tp->tv_nsec = tv.tv_usec * 1000;
694
695 return res;
696}
697#endif
698
699#ifdef F_clock_settime
700int clock_settime(clockid_t clk_id, const struct timespec *tp) {
701 // TODO: implement using sceCdWriteClock
702 errno = EPERM;
703 return -1;
704}
705#endif
706
707#ifdef F_truncate
708int truncate(const char *path, off_t length)
709{
710 ssize_t bytes_read;
711 int fd, res;
712 char buff[length];
713
714 fd = open(path, O_RDONLY);
715 if (fd < 0) {
716 errno = ENOENT;
717 return -1;
718 }
719
720 bytes_read = read(fd, &buff, length);
721 close(fd);
722 if (bytes_read < length) {
723 errno = EFBIG;
724 return -1;
725 }
726
727 fd = open (path, O_TRUNC|O_WRONLY);
728 if (fd < 0) {
729 errno = ENOENT;
730 return -1;
731 }
732
733 res = write(fd, &buff, length);
734 close(fd);
735 return res;
736}
737#endif
738
739#ifdef F_symlink
740int symlink(const char *target, const char *linkpath)
741{
742 char dest_target[MAXNAMLEN + 1];
743 char dest_linkpath[MAXNAMLEN + 1];
744
745 if(__path_absolute(target, dest_target, MAXNAMLEN) < 0) {
746 errno = ENAMETOOLONG;
747 return -1;
748 }
749
750 if(__path_absolute(linkpath, dest_linkpath, MAXNAMLEN) < 0) {
751 errno = ENAMETOOLONG;
752 return -1;
753 }
754
755 if (_libcglue_fdman_path_ops == NULL || _libcglue_fdman_path_ops->symlink == NULL)
756 {
757 errno = ENOSYS;
758 return -1;
759 }
760
761 return __transform_errno(_libcglue_fdman_path_ops->symlink(dest_target, dest_linkpath));
762}
763#endif
764
765#ifdef F_readlink
766ssize_t readlink(const char *path, char *buf, size_t bufsiz)
767{
768 char dest[MAXNAMLEN + 1];
769
770 if(__path_absolute(path, dest, MAXNAMLEN) < 0) {
771 errno = ENAMETOOLONG;
772 return -1;
773 }
774
775 if (_libcglue_fdman_path_ops == NULL || _libcglue_fdman_path_ops->readlink == NULL)
776 {
777 errno = ENOSYS;
778 return -1;
779 }
780
781 return __transform_errno(_libcglue_fdman_path_ops->readlink(dest, buf, bufsiz));
782}
783#endif
784
785#ifdef F_utime
786int utime(const char *pathname, const struct utimbuf *times)
787{
788 // TODO: implement in terms of chstat
789 errno = ENOSYS;
790 return -1; /* not supported */
791}
792#endif
793
794#ifdef F_fchown
795int fchown(int fd, uid_t owner, gid_t group)
796{
797 errno = ENOSYS;
798 return -1; /* not supported */
799}
800#endif
801
802#ifdef F_getrandom
803ssize_t getrandom(void *buf, size_t buflen, unsigned int flags)
804{
805 (void)flags;
806
807 arc4random_buf(buf, buflen);
808 return buflen;
809}
810#endif
811
812#ifdef F__getentropy
813int _getentropy(void *buf, size_t buflen)
814{
815 u8 *buf_cur = buf;
816 int i;
817 // Restrict buffer size as documented in the man page
818 if (buflen > 256)
819 {
820 errno = EIO;
821 return -1;
822 }
823 // TODO: get proper entropy from e.g.
824 // * RTC
825 // * uninitialized memory
826 // * Mechacon temperature
827 for (i = 0; i < buflen; i += 1)
828 {
829 // Performance counter low buts should be changed for each call to cpu_ticks
830 buf_cur[i] = (u8)(cpu_ticks() & 0xff);
831 }
832 return 0;
833}
834#endif
835
836#ifdef F__isatty
837int _isatty(int fd)
838{
839 errno = ENOSYS;
840 return -1; /* not supported */
841}
842#endif
843
844#ifdef F_chmod
845int chmod(const char *pathname, mode_t mode)
846{
847 errno = ENOSYS;
848 return -1; /* not supported */
849}
850#endif
851
852#ifdef F_fchmod
853int fchmod(int fd, mode_t mode)
854{
855 errno = ENOSYS;
856 return -1; /* not supported */
857}
858#endif
859
860#ifdef F_pathconf
861long int pathconf(const char *path, int name)
862{
863 errno = ENOSYS;
864 return -1; /* not supported */
865}
866#endif
867
868#ifdef F_fsync
869int fsync(int fd) {
870 // TODO: implement in terms of sync
871 return 0;
872}
873#endif
874
875#ifdef F_getuid
876uid_t getuid(void) {
877 return __dummy_passwd.pw_uid;
878}
879#endif
880
881#ifdef F_geteuid
882uid_t geteuid(void) {
883 return __dummy_passwd.pw_uid;
884}
885#endif
886
887#ifdef F_getpwuid
888struct passwd *getpwuid(uid_t uid) {
889 /* There's no support for users */
890 return &__dummy_passwd;
891}
892#endif
893
894#ifdef F_getpwnam
895struct passwd *getpwnam(const char *name) {
896 /* There's no support for users */
897 return &__dummy_passwd;
898}
899#endif
900
901#ifdef F_libcglue_get_fd_info
902_libcglue_fdman_fd_info_t *libcglue_get_fd_info(int fd) {
903 if (!__IS_FD_VALID(fd)) {
904 errno = EBADF;
905 return NULL;
906 }
907
908 return &(__descriptormap[fd]->info);
909}
910#endif
911
912#ifdef F_ps2sdk_get_iop_fd
913int ps2sdk_get_iop_fd(int fd)
914{
916 fdinfo = libcglue_get_fd_info(fd);
917 if (fdinfo == NULL)
918 {
919 return -EBADF;
920 }
921 if (fdinfo->ops == NULL || fdinfo->ops->getfd == NULL)
922 {
923 return -ENOSYS;
924 }
925 return fdinfo->ops->getfd(fdinfo->userdata);
926}
927#endif
928
929#ifdef F_ps2sdk_get_iop_filename
930char *ps2sdk_get_iop_filename(int fd)
931{
933 fdinfo = libcglue_get_fd_info(fd);
934 if (fdinfo == NULL)
935 {
936 return NULL;
937 }
938 if (fdinfo->ops == NULL || fdinfo->ops->getfilename == NULL)
939 {
940 return NULL;
941 }
942 return fdinfo->ops->getfilename(fdinfo->userdata);
943}
944#endif
945
946#ifdef F__ps2sdk_close
947int _ps2sdk_close(int fd)
948{
950 fdinfo = libcglue_get_fd_info(fd);
951 if (fdinfo == NULL)
952 {
953 return -EBADF;
954 }
955 if (fdinfo->ops == NULL || fdinfo->ops->close == NULL)
956 {
957 return -ENOSYS;
958 }
959 return fdinfo->ops->close(fdinfo->userdata);
960}
961#endif
962
963#ifdef F__ps2sdk_dclose
964int _ps2sdk_dclose(int fd)
965{
966 return _ps2sdk_close(fd);
967}
968#endif
969
970#ifdef F__ps2sdk_read
971int _ps2sdk_read(int fd, void *buf, int nbytes)
972{
974 fdinfo = libcglue_get_fd_info(fd);
975 if (fdinfo == NULL)
976 {
977 return -EBADF;
978 }
979 if (fdinfo->ops == NULL || fdinfo->ops->read == NULL)
980 {
981 return -ENOSYS;
982 }
983 return fdinfo->ops->read(fdinfo->userdata, buf, nbytes);
984}
985#endif
986
987#ifdef F__ps2sdk_lseek
988int _ps2sdk_lseek(int fd, int offset, int whence)
989{
991 fdinfo = libcglue_get_fd_info(fd);
992 if (fdinfo == NULL)
993 {
994 return -EBADF;
995 }
996 if (fdinfo->ops == NULL || fdinfo->ops->lseek == NULL)
997 {
998 return -ENOSYS;
999 }
1000 return fdinfo->ops->lseek(fdinfo->userdata, offset, whence);
1001}
1002#endif
1003
1004#ifdef F__ps2sdk_lseek64
1005int64_t _ps2sdk_lseek64(int fd, int64_t offset, int whence)
1006{
1008 fdinfo = libcglue_get_fd_info(fd);
1009 if (fdinfo == NULL)
1010 {
1011 return -EBADF;
1012 }
1013 if (fdinfo->ops == NULL || fdinfo->ops->lseek64 == NULL)
1014 {
1015 return -ENOSYS;
1016 }
1017 return fdinfo->ops->lseek64(fdinfo->userdata, offset, whence);
1018}
1019#endif
1020
1021#ifdef F__ps2sdk_write
1022int _ps2sdk_write(int fd, const void *buf, int nbytes)
1023{
1025 fdinfo = libcglue_get_fd_info(fd);
1026 if (fdinfo == NULL)
1027 {
1028 return -EBADF;
1029 }
1030 if (fdinfo->ops == NULL || fdinfo->ops->write == NULL)
1031 {
1032 return -ENOSYS;
1033 }
1034 return fdinfo->ops->write(fdinfo->userdata, buf, nbytes);
1035}
1036#endif
1037
1038#ifdef F__ps2sdk_ioctl
1039int _ps2sdk_ioctl(int fd, int request, void *data)
1040{
1042 fdinfo = libcglue_get_fd_info(fd);
1043 if (fdinfo == NULL)
1044 {
1045 return -EBADF;
1046 }
1047 if (fdinfo->ops == NULL || fdinfo->ops->ioctl == NULL)
1048 {
1049 return -ENOSYS;
1050 }
1051 return fdinfo->ops->ioctl(fdinfo->userdata, request, data);
1052}
1053#endif
1054
1055#ifdef F__ps2sdk_ioctl2
1056int _ps2sdk_ioctl2(int fd, int request, void *arg, unsigned int arglen, void *buf, unsigned int buflen)
1057{
1059 fdinfo = libcglue_get_fd_info(fd);
1060 if (fdinfo == NULL)
1061 {
1062 return -EBADF;
1063 }
1064 if (fdinfo->ops == NULL || fdinfo->ops->ioctl == NULL)
1065 {
1066 return -ENOSYS;
1067 }
1068 return fdinfo->ops->ioctl2(fdinfo->userdata, request, arg, arglen, buf, buflen);
1069}
1070#endif
1071
1072#ifdef F__ps2sdk_dread
1073int _ps2sdk_dread(int fd, struct dirent *dir)
1074{
1076 fdinfo = libcglue_get_fd_info(fd);
1077 if (fdinfo == NULL)
1078 {
1079 return -EBADF;
1080 }
1081 if (fdinfo->ops == NULL || fdinfo->ops->dread == NULL)
1082 {
1083 return -ENOSYS;
1084 }
1085 return fdinfo->ops->dread(fdinfo->userdata, dir);
1086}
1087#endif
1088
1089/* ATFILE functions */
1090
1091#ifdef F_openat
1092int openat(int dirfd, const char *pathname, int flags, ...)
1093{
1094 // TODO: Do better implementation following https://linux.die.net/man/2/openat
1095 // for now use the same as open
1096
1097 // Extract mode from variable arguments
1098 va_list args;
1099 va_start(args, flags);
1100
1101 // Get the mode argument
1102 int mode = va_arg(args, int);
1103
1104 // Clean up the va_list
1105 va_end(args);
1106 return open(pathname, flags, mode);
1107}
1108#endif /* F_openat */
1109
1110#ifdef F_renameat
1111int renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath)
1112{
1113 // TODO: Do better implementation following https://linux.die.net/man/2/renameat
1114 // for now use the same as rename
1115 return rename(oldpath, newpath);
1116}
1117#endif /* F_renameat */
1118
1119#ifdef F_fchmodat
1120int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags)
1121{
1122 // TODO: Do better implementation following https://linux.die.net/man/2/fchmodat
1123 // for now use the same as chmod
1124 return chmod(pathname, mode);
1125}
1126#endif /* F_fchmodat */
1127
1128#ifdef F_fstatat
1129int fstatat(int dirfd, const char *pathname, struct stat *buf, int flags)
1130{
1131 // TODO: Do better implementation following https://linux.die.net/man/2/fstatat
1132 // for now use the same as stat
1133 return stat(pathname, buf);
1134}
1135#endif /* F_fstatat */
1136
1137#ifdef F_mkdirat
1138int mkdirat(int dirfd, const char *pathname, mode_t mode)
1139{
1140 // TODO: Do better implementation following https://linux.die.net/man/2/mkdirat
1141 // for now use the same as mkdir
1142 return mkdir(pathname, mode);
1143}
1144#endif /* F_mkdirat */
1145
1146#ifdef F_faccessat
1147int faccessat(int dirfd, const char *pathname, int mode, int flags)
1148{
1149 // TODO: Do better implementation following https://linux.die.net/man/2/faccessat
1150 // for now use the same as access
1151 return access(pathname, mode);
1152}
1153#endif /* F_faccessat */
1154
1155#ifdef F_fchownat
1156int fchownat(int dirfd, const char *pathname, uid_t owner, gid_t group, int flags)
1157{
1158 // TODO: Do better implementation following https://linux.die.net/man/2/fchownat
1159 // for now use the same as chown
1160 return chown(pathname, owner, group);
1161}
1162#endif /* F_fchownat */
1163
1164#ifdef F_linkat
1165int linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, int flags) {
1166 // TODO: Do better implementation following https://linux.die.net/man/2/linkat
1167 // for now use the same as link
1168 return link(oldpath, newpath);
1169}
1170#endif /* F_linkat */
1171
1172#ifdef F_readlinkat
1173int readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz)
1174{
1175 // TODO: Do better implementation following https://linux.die.net/man/2/linkat
1176 // for now use the same as readlink
1177 return readlink(pathname, buf, bufsiz);
1178}
1179#endif /* F_readlinkat */
1180
1181#ifdef F_unlinkat
1182int unlinkat(int dirfd, const char *pathname, int flags)
1183{
1184 // If flags contains AT_REMOVEDIR, then the path refers to a directory.
1185 // Otherwise, the path refers to a file.
1186 if (flags & AT_REMOVEDIR) {
1187 return rmdir(pathname);
1188 }
1189 else {
1190 return unlink(pathname);
1191 }
1192}
1193#endif /* F_unlinkat */
1194
1195#ifdef F_dup
1196int dup(int oldfd)
1197{
1198 if (!__IS_FD_VALID(oldfd)) {
1199 errno = EBADF;
1200 return -1;
1201 }
1202
1203 return __fdman_get_dup_descriptor(oldfd);
1204}
1205#endif /* F_dup */
1206
1207#ifdef F_dup2
1208int dup2(int oldfd, int newfd)
1209{
1210 if (!__IS_FD_VALID(oldfd)) {
1211 errno = EBADF;
1212 return -1;
1213 }
1214
1215 if (oldfd == newfd) {
1216 return oldfd;
1217 }
1218 if (newfd < 0) {
1219 errno = EBADF;
1220 return -1;
1221 }
1222 if (__descriptormap[newfd]) {
1223 close(newfd);
1224 }
1225 return __fdman_get_dup2_descriptor(oldfd, newfd);
1226}
1227#endif /* F_dup2 */
#define ENOENT
Definition errno.h:23
#define EFAULT
Definition errno.h:47
#define ENAMETOOLONG
Definition errno.h:191
#define ENOSYS
Definition errno.h:185
#define ENOMEM
Definition errno.h:43
#define EIO
Definition errno.h:29
#define EACCES
Definition errno.h:45
#define EBADF
Definition errno.h:37
#define EPERM
Definition errno.h:21
#define EFBIG
Definition errno.h:73
Definition time.h:29
u32 count
start sector of fragmented bd/file