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 <grp.h>
25#include <sys/termios.h>
26#include <sys/time.h>
27#include <sys/timeb.h>
28#include <sys/times.h>
29#include <sys/utime.h>
30#include <sys/uio.h>
31#include <sys/stat.h>
32#include <sys/signal.h>
33#include <sys/types.h>
34#include <sys/random.h>
35
36// Include all integer types for compile time checking of:
37// - compiler (gcc)
38// - libc (newlib)
39#include <stdint.h>
40#include <limits.h>
41#include <inttypes.h>
42#include <tamtypes.h>
43
44#define NEWLIB_PORT_AWARE
45#include "io_common.h"
46#include "ps2sdkapi.h"
47#include "timer_alarm.h"
48#include "fdman.h"
49
50/* Functions from cwd.c */
51extern char __cwd[MAXNAMLEN + 1];
52extern size_t __cwd_len;
53int __path_absolute(const char *in, char *out, int len);
54
55extern void * _end;
56
57#ifdef F___dummy_passwd
58char __dummy_passwd_loginbuf[16] = "ps2user";
59/* the present working directory variable. */
60struct passwd __dummy_passwd = { &__dummy_passwd_loginbuf[0], "xxx", 1000, 1000, "", "", "/", "" };
61#else
62extern char __dummy_passwd_loginbuf[16];
63extern struct passwd __dummy_passwd;
64#endif
65
66#ifdef F___dummy_group
67static char *__dummy_group_members[2] = {&__dummy_passwd_loginbuf[0], NULL};
68struct group __dummy_group = { "ps2group", "xxx", 1000, &__dummy_group_members[0]};
69#else
70extern struct group __dummy_group;
71#endif
72
73#ifdef F___transform_errno
74int __transform_errno(int 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
83int __transform_errno(int res);
84#endif
85
86#ifdef F___transform64_errno
87int64_t __transform64_errno(int64_t res) {
88 /* On error, -1 is returned and errno is set to indicate the error. */
89 if (res < 0) {
90 errno = -res;
91 return -1;
92 }
93 return res;
94}
95#else
96int64_t __transform64_errno(int64_t res);
97#endif
98
99#if INT_MAX != 0x7fffffffL
100 #error "INT_MAX != 0x7fffffffL"
101#endif
102#ifndef LONG_MAX
103 #error "LONG_MAX not defined"
104#endif
105#if LONG_MAX != 0x7fffffffL
106 #error "LONG_MAX != 0x7fffffffL"
107#endif
108
109#define ct_assert(e) {enum { ct_assert_value = 1/(!!(e)) };}
110#ifdef F_compile_time_check
111void compile_time_check() {
112 // Compiler (ABI n32)
113 ct_assert(sizeof(unsigned char)==1);
114 ct_assert(sizeof(unsigned short)==2);
115 ct_assert(sizeof(unsigned int)==4);
116 ct_assert(sizeof(unsigned long)==4);
117 ct_assert(sizeof(unsigned long long)==8);
118 ct_assert(sizeof(unsigned int __attribute__(( mode(TI) )))==16);
119 ct_assert(sizeof(void *)==4);
120
121 // Defined in tamtypes.h (ps2sdk)
122 ct_assert(sizeof(u8)==1);
123 ct_assert(sizeof(u16)==2);
124 ct_assert(sizeof(u32)==4);
125 ct_assert(sizeof(u64)==8);
126 ct_assert(sizeof(u128)==16);
127
128 // Defined in inttypes.h/stdint.h (newlib)
129 ct_assert(sizeof(uint8_t)==1);
130 ct_assert(sizeof(uint16_t)==2);
131 ct_assert(sizeof(uint32_t)==4);
132 ct_assert(sizeof(uint64_t)==8);
133}
134#endif
135
136#ifdef F__open
137// Called from newlib openr.c
138int _open(const char *buf, int flags, ...) {
139 int iop_fd, fd;
140 int mode;
142 va_list alist;
143 char t_fname[MAXNAMLEN + 1];
144
145 va_start(alist, flags);
146 mode = va_arg(alist, int); // Retrieve the mode argument, regardless of whether it is expected or not.
147 va_end(alist);
148
149 if(__path_absolute(buf, t_fname, MAXNAMLEN) < 0) {
150 errno = ENAMETOOLONG;
151 return -1;
152 }
153
154 if (_libcglue_fdman_path_ops == NULL || _libcglue_fdman_path_ops->open == NULL)
155 {
156 errno = ENOSYS;
157 return -1;
158 }
159
160 fd = __fdman_get_new_descriptor();
161 if (fd == -1)
162 {
163 errno = ENOMEM;
164 return -1;
165 }
166
167 info = &(__descriptormap[fd]->info);
168 iop_fd = _libcglue_fdman_path_ops->open(info, t_fname, flags, mode);
169 if (iop_fd < 0)
170 {
171 __fdman_release_descriptor(fd);
172 return __transform_errno(iop_fd);
173 }
174 __descriptormap[fd]->flags = flags;
175 return fd;
176}
177#endif
178
179#ifdef F_pipe
180// Called from newlib wordexp.c, popen.c
181int pipe(int fildes[2])
182{
183 errno = ENOSYS;
184 return -1;
185}
186#endif
187
188#ifdef F__close
189// Called from newlib closer.c
190int _close(int fd) {
191 int ret = 0;
192
193 if (!__IS_FD_VALID(fd)) {
194 errno = EBADF;
195 return -1;
196 }
197
198 if (__descriptormap[fd]->ref_count == 1)
199 {
201
202 fdinfo = &(__descriptormap[fd]->info);
203 if (fdinfo->ops != NULL && fdinfo->ops->close != NULL)
204 {
205 ret = __transform_errno(fdinfo->ops->close(fdinfo->userdata));
206 }
207 }
208 __fdman_release_descriptor(fd);
209 return ret;
210}
211#endif
212
213#ifdef F__read
214// Called from newlib readr.c
215int _read(int fd, void *buf, size_t nbytes) {
216 if (!__IS_FD_VALID(fd)) {
217 errno = EBADF;
218 return -1;
219 }
220
222
223 fdinfo = &(__descriptormap[fd]->info);
224 if (fdinfo->ops == NULL || fdinfo->ops->read == NULL)
225 {
226 errno = ENOSYS;
227 return -1;
228 }
229 return __transform_errno(fdinfo->ops->read(fdinfo->userdata, buf, nbytes));
230}
231#endif
232
233#ifdef F__write
234// Called from newlib writer.c
235int _write(int fd, const void *buf, size_t nbytes) {
236 if (!__IS_FD_VALID(fd)) {
237 errno = EBADF;
238 return -1;
239 }
240
242
243 fdinfo = &(__descriptormap[fd]->info);
244 if (fdinfo->ops == NULL || fdinfo->ops->write == NULL)
245 {
246 errno = ENOSYS;
247 return -1;
248 }
249 return __transform_errno(fdinfo->ops->write(fdinfo->userdata, buf, nbytes));
250}
251#endif
252
253#ifdef F__stat
254// Called from newlib statr.c
255int _stat(const char *path, struct stat *buf) {
256 char dest[MAXNAMLEN + 1];
257
258 if(__path_absolute(path, dest, MAXNAMLEN) < 0) {
259 errno = ENAMETOOLONG;
260 return -1;
261 }
262
263 if (_libcglue_fdman_path_ops == NULL || _libcglue_fdman_path_ops->stat == NULL)
264 {
265 errno = ENOSYS;
266 return -1;
267 }
268
269 return __transform_errno(_libcglue_fdman_path_ops->stat(dest, buf));
270}
271#endif
272
273#ifdef F_lstat
274// Called from newlib glob.c, nftw.c
275int lstat(const char *path, struct stat *buf) {
276 return stat(path, buf);
277}
278#endif
279
280#ifdef F__fstat
281// Called from newlib fstatr.c
282int _fstat(int fd, struct stat *buf) {
283 if (!__IS_FD_VALID(fd)) {
284 errno = EBADF;
285 return -1;
286 }
287
289 char *filename;
290
291 fdinfo = &(__descriptormap[fd]->info);
292 if (fdinfo->ops == NULL || fdinfo->ops->getfilename == NULL)
293 {
294 errno = ENOSYS;
295 return -1;
296 }
297 filename = fdinfo->ops->getfilename(fdinfo->userdata);
298 if (filename == NULL)
299 {
300 errno = ENOENT;
301 return -1;
302 }
303
304 if (_libcglue_fdman_path_ops == NULL || _libcglue_fdman_path_ops->stat == NULL)
305 {
306 errno = ENOSYS;
307 return -1;
308 }
309
310 return __transform_errno(_libcglue_fdman_path_ops->stat(filename, buf));
311}
312#endif
313
314#ifdef F_access
315// Called from newlib nftw.c
316int access(const char *fn, int flags) {
317 struct stat s;
318 if (stat(fn, &s))
319 return -1;
320 if (s.st_mode & S_IFDIR)
321 return 0;
322 if (flags & W_OK) {
323 if (s.st_mode & S_IWRITE)
324 return 0;
325 errno = EACCES;
326 return -1;
327 }
328 return 0;
329}
330#endif
331
332#ifdef F__fcntl
333// Called from newlib fcntlr.c
334int _fcntl(int fd, int cmd, ...)
335{
336 if (!__IS_FD_VALID(fd)) {
337 errno = EBADF;
338 return -1;
339 }
340
341 switch (cmd)
342 {
343 case F_DUPFD:
344 {
345 return __fdman_get_dup_descriptor(fd);
346 break;
347 }
348 case F_GETFL:
349 {
350 return __descriptormap[fd]->flags;
351 break;
352 }
353 case F_SETFL:
354 {
355 int newfl, rv;
356 va_list args;
357
358 rv = 0;
359
360 va_start (args, cmd); /* Initialize the argument list. */
361 newfl = va_arg(args, int);
362 va_end (args); /* Clean up. */
363
364 __descriptormap[fd]->flags = newfl;
365
366 {
368
369 fdinfo = &(__descriptormap[fd]->info);
370
371 if (fdinfo->ops != NULL && fdinfo->ops->fcntl_f_setfl != NULL)
372 {
373 rv = __transform_errno(fdinfo->ops->fcntl_f_setfl(fdinfo->userdata, newfl));
374 }
375 }
376 return rv;
377 }
378 case F_SETFD:
379 {
380 int newfl;
381 va_list args;
382
383 va_start (args, cmd); /* Initialize the argument list. */
384 newfl = va_arg(args, int);
385 va_end (args); /* Clean up. */
386
387 __descriptormap[fd]->flags = newfl;
388 return 0;
389 break;
390 }
391 }
392
393 errno = EBADF;
394 return -1;
395}
396#endif /* F__fcntl */
397
398#ifdef F__ioctl
399// This is actually not called from newlib, but the _ioctl symbol is checked by
400// ps2sdkapi.c and fileXio_ps2sdkapi.c. Perhaps it was later renamed to _ps2sdk_ioctl?
401// For consistency, _ioctl is implemented as an errno alternative to _ps2sdk_ioctl.
402int _ioctl(int fd, int request, void *data) {
404 fdinfo = libcglue_get_fd_info(fd);
405 if (fdinfo == NULL)
406 {
407 errno = EBADF;
408 return -1;
409 }
410 if (fdinfo->ops == NULL || fdinfo->ops->ioctl == NULL)
411 {
412 errno = ENOSYS;
413 return -1;
414 }
415 return __transform_errno(fdinfo->ops->ioctl(fdinfo->userdata, request, data));
416}
417#endif /* F__ioctl */
418
419#ifdef F_getdents
420// Called from newlib readdir.c, readdir_r.c
421int getdents(int fd, void *dd_buf, int count)
422{
423 struct dirent *dirp;
424 int rv, read;
425
426 read = 0;
427 dirp = (struct dirent *)dd_buf;
428
429 {
431
432 fdinfo = &(__descriptormap[fd]->info);
433 rv = -ENOSYS;
434 if (fdinfo->ops != NULL && fdinfo->ops->dread != NULL)
435 {
436 rv = __transform_errno(fdinfo->ops->dread(fdinfo->userdata, dirp));
437 }
438 }
439 if (rv < 0) {
440 return __transform_errno(rv);
441 } else if (rv == 0) {
442 return read;
443 }
444
445 read += sizeof(struct dirent);
446 dirp->d_reclen = count;
447
448 return read;
449}
450#endif
451
452#ifdef F__lseek
453// Called from newlib lseekr.c
454off_t _lseek(int fd, off_t offset, int whence)
455{
456 if (!__IS_FD_VALID(fd)) {
457 errno = EBADF;
458 return -1;
459 }
460
462
463 fdinfo = &(__descriptormap[fd]->info);
464 if (fdinfo->ops == NULL || fdinfo->ops->lseek == NULL)
465 {
466 errno = ENOSYS;
467 return -1;
468 }
469 return __transform_errno(fdinfo->ops->lseek(fdinfo->userdata, offset, whence));
470}
471#endif
472
473#ifdef F_lseek64
474off64_t lseek64(int fd, off64_t offset, int whence)
475{
476 if (!__IS_FD_VALID(fd)) {
477 errno = EBADF;
478 return -1;
479 }
480
482
483 fdinfo = &(__descriptormap[fd]->info);
484 if (fdinfo->ops == NULL || fdinfo->ops->lseek64 == NULL)
485 {
486 errno = ENOSYS;
487 return -1;
488 }
489 return __transform64_errno(fdinfo->ops->lseek64(fdinfo->userdata, offset, whence));
490}
491#endif
492
493#ifdef F_chdir
494int chdir(const char *path) {
495 char dest[MAXNAMLEN + 1];
496
497 if(__path_absolute(path, dest, MAXNAMLEN) < 0) {
498 errno = ENAMETOOLONG;
499 return -1;
500 }
501
502 strncpy(__cwd, dest, sizeof(__cwd));
503 __cwd_len = strnlen(__cwd, sizeof(__cwd));
504 return 0;
505}
506#endif
507
508#ifdef F_fchdir
509int fchdir(int fd)
510{
511 errno = ENOSYS;
512 return -1;
513}
514#endif
515
516#ifdef F__mkdir
517// Called from newlib mkdirr.c
518int _mkdir(const char *path, mode_t mode)
519{
520 char dest[MAXNAMLEN + 1];
521
522 if(__path_absolute(path, dest, MAXNAMLEN) < 0) {
523 errno = ENAMETOOLONG;
524 return -1;
525 }
526
527 if (_libcglue_fdman_path_ops == NULL || _libcglue_fdman_path_ops->mkdir == NULL)
528 {
529 errno = ENOSYS;
530 return -1;
531 }
532
533 return __transform_errno(_libcglue_fdman_path_ops->mkdir(dest, mode));
534}
535#else
536int _mkdir(const char *path, mode_t mode);
537#endif
538
539#ifdef F_mkdir
540int mkdir(const char *path, mode_t mode)
541{
542 return _mkdir(path, mode);
543}
544#else
545int mkdir(const char *path, mode_t mode);
546#endif
547
548#ifdef F_rmdir
549int rmdir(const char *path) {
550 char dest[MAXNAMLEN + 1];
551
552 if(__path_absolute(path, dest, MAXNAMLEN) < 0) {
553 errno = ENAMETOOLONG;
554 return -1;
555 }
556
557 if (_libcglue_fdman_path_ops == NULL || _libcglue_fdman_path_ops->rmdir == NULL)
558 {
559 errno = ENOSYS;
560 return -1;
561 }
562
563 return __transform_errno(_libcglue_fdman_path_ops->rmdir(dest));
564}
565#endif
566
567#ifdef F__link
568// Called from newlib linkr.c
569int _link(const char *old, const char *new) {
570 errno = ENOSYS;
571 return -1; /* not supported */
572}
573#endif
574
575#ifdef F__unlink
576// Called from newlib unlinkr.c
577int _unlink(const char *path) {
578 char dest[MAXNAMLEN + 1];
579 if(__path_absolute(path, dest, MAXNAMLEN) < 0) {
580 errno = ENAMETOOLONG;
581 return -1;
582 }
583
584 if (_libcglue_fdman_path_ops == NULL || _libcglue_fdman_path_ops->remove == NULL)
585 {
586 errno = ENOSYS;
587 return -1;
588 }
589
590 return __transform_errno(_libcglue_fdman_path_ops->remove(dest));
591}
592#endif
593
594#ifdef F__rename
595// Called from newlib renamer.c
596int _rename(const char *old, const char *new) {
597 char oldname[MAXNAMLEN + 1];
598 char newname[MAXNAMLEN + 1];
599
600 if(__path_absolute(old, oldname, MAXNAMLEN) < 0) {
601 errno = ENAMETOOLONG;
602 return -1;
603 }
604
605 if(__path_absolute(new, newname, MAXNAMLEN) < 0) {
606 errno = ENAMETOOLONG;
607 return -1;
608 }
609
610 if (_libcglue_fdman_path_ops == NULL || _libcglue_fdman_path_ops->rename == NULL)
611 {
612 errno = ENOSYS;
613 return -1;
614 }
615
616 return __transform_errno(_libcglue_fdman_path_ops->rename(oldname, newname));
617}
618#endif
619
620#ifdef F_pause
621int pause(void)
622{
623 errno = ENOSYS;
624 return -1;
625}
626#endif
627
628#ifdef F_getitimer
629int getitimer(int which, struct itimerval *value)
630{
631 errno = ENOSYS;
632 return -1;
633}
634#endif
635
636#ifdef F_setitimer
637int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue)
638{
639 errno = ENOSYS;
640 return -1;
641}
642#endif
643
644#ifdef F_sched_yield
645int sched_yield(void)
646{
647 return 0;
648}
649#endif
650
651#ifdef F__getpid
652// Called from newlib signalr.c
653int _getpid(void) {
654 return GetThreadId();
655}
656#endif
657
658#ifdef F_getppid
659pid_t getppid(void)
660{
661 errno = ENOSYS;
662 return (pid_t) -1;
663}
664#endif
665
666#ifdef F__kill
667// Called from newlib signalr.c
668int _kill(int pid, int sig) {
669#if 0 // needs to be tested first
670 // null signal: do error checking on pid only
671 if (sig == 0)
672 return pid == getpid() ? 0 : -1;
673
674 if (pid == getpid()) {
675 ExitDeleteThread();
676 // NOTE: ExitDeleteThread does not return
677 return 0;
678 }
679#endif
680 (void)pid;
681 (void)sig;
682 errno = ENOSYS;
683 return -1; /* not supported */
684}
685#endif
686
687#ifdef F_sigprocmask
688// Called from newlib hash_page.c
689int sigprocmask(int how, const sigset_t *set, sigset_t *oset)
690{
691 errno = ENOSYS;
692 return -1; /* not supported */
693}
694#endif
695
696#ifdef F_sigaction
697int sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
698{
699 errno = ENOSYS;
700 return -1; /* not supported */
701}
702#endif
703
704#ifdef F__fork
705// Called from newlib execr.c
706pid_t _fork(void) {
707 errno = ENOSYS;
708 return (pid_t) -1; /* not supported */
709}
710#endif
711
712#ifdef F_vfork
713// Called from newlib popen.c
714pid_t vfork(void)
715{
716 errno = ENOSYS;
717 return (pid_t) -1; /* not supported */
718}
719#endif
720
721#ifdef F__wait
722// Called from newlib execr.c
723pid_t _wait(int *unused) {
724 errno = ENOSYS;
725 return (pid_t) -1; /* not supported */
726}
727#endif
728
729#ifdef F_waitpid
730// Called from newlib wordexp.c, popen.c
731pid_t waitpid(pid_t pid, int *stat_loc, int options)
732{
733 errno = ENOSYS;
734 return (pid_t) -1; /* not supported */
735}
736#endif
737
738#ifdef F__execve
739// Called from newlib execr.c, execl.c, execle.c, execv.c, execve.c
740int _execve(const char *name, char *const argv[], char *const env[]) {
741 errno = ENOSYS;
742 return (pid_t) -1; /* not supported */
743}
744#endif
745
746#ifdef F__system
747int _system(const char *command)
748{
749 if (!command)
750 return 0;
751 errno = ENOSYS;
752 return -1;
753}
754#endif
755
756#ifdef F__sbrk
757// Called from newlib sbrkr.c
758void * _sbrk(size_t incr) {
759 static void * _heap_ptr = &_end;
760 void *mp, *ret = (void *)-1;
761
762 if (incr == 0)
763 return _heap_ptr;
764
765 /* If the area we want to allocated is past the end of our heap, we have a problem. */
766 mp = _heap_ptr + incr;
767 if (mp <= EndOfHeap()) {
768 ret = _heap_ptr;
769 _heap_ptr = mp;
770 }
771
772 return ret;
773}
774#endif
775
776#ifdef F__gettimeofday
777// Called from newlib gettimeofdayr.c
778int _gettimeofday(struct timeval *tv, struct timezone *tz)
779{
780 if (tv == NULL)
781 {
782 errno = EFAULT;
783 return -1;
784 }
785
786 {
787 u32 busclock_sec;
788 u32 busclock_usec;
789
790 TimerBusClock2USec(GetTimerSystemTime(), &busclock_sec, &busclock_usec);
791 tv->tv_sec = (time_t)(_ps2sdk_rtc_offset_from_busclk + ((s64)busclock_sec));
792 tv->tv_usec = busclock_usec;
793 }
794
795 if (tz != NULL)
796 {
797 tz->tz_minuteswest = _timezone / 60;
798 tz->tz_dsttime = 0;
799 }
800
801 return 0;
802}
803#endif
804
805#ifdef F__times
806// Called from newlib timesr.c
807clock_t _times(struct tms *buffer) {
808 clock_t clk;
809 u32 busclock_sec;
810 u32 busclock_usec;
811
812 TimerBusClock2USec(GetTimerSystemTime(), &busclock_sec, &busclock_usec);
813 clk = busclock_sec * CLOCKS_PER_SEC + busclock_usec;
814
815 if (buffer != NULL) {
816 buffer->tms_utime = clk;
817 buffer->tms_stime = 0;
818 buffer->tms_cutime = 0;
819 buffer->tms_cstime = 0;
820 }
821
822 return clk;
823}
824#endif
825
826#ifdef F_ftime
827int ftime(struct timeb *tb) {
828 struct timeval tv;
829 struct timezone tz;
830
831 gettimeofday(&tv, &tz);
832
833 tb->time = tv.tv_sec;
834 tb->millitm = tv.tv_usec / 1000;
835 tb->timezone = tz.tz_minuteswest;
836 tb->dstflag = tz.tz_dsttime;
837
838 return 0;
839}
840#endif
841
842#ifdef F_clock_getres
843int clock_getres(clockid_t clk_id, struct timespec *res) {
844 struct timeval tv;
845 int ret;
846
847 ret = gettimeofday(&tv, NULL);
848
849 /* Return the actual time since epoch */
850 res->tv_sec = tv.tv_sec;
851 res->tv_nsec = tv.tv_usec * 1000;
852
853 return ret;
854}
855#endif
856
857#ifdef F_clock_gettime
858int clock_gettime(clockid_t clk_id, struct timespec *tp) {
859 struct timeval tv;
860 int res;
861
862 res = gettimeofday(&tv, NULL);
863
864 /* Return the actual time since epoch */
865 tp->tv_sec = tv.tv_sec;
866 tp->tv_nsec = tv.tv_usec * 1000;
867
868 return res;
869}
870#endif
871
872#ifdef F_clock_settime
873int clock_settime(clockid_t clk_id, const struct timespec *tp) {
874 // TODO: implement using sceCdWriteClock
875 errno = EPERM;
876 return -1;
877}
878#endif
879
880#ifdef F_readv
881__attribute__((weak))
882ssize_t readv(int fd, const struct iovec *iov, int iovcnt)
883{
884 int i;
885 ssize_t size_sum;
886
887 size_sum = 0;
888 for (i = 0; i < iovcnt; i += 1)
889 {
890 ssize_t size_cur;
891
892 size_cur = read(fd, iov[i].iov_base, iov[i].iov_len);
893 if (size_cur < 0)
894 return size_cur;
895 size_sum += size_cur;
896 if (size_cur != iov[i].iov_len)
897 break;
898 }
899 return size_sum;
900}
901#endif
902
903#ifdef F_writev
904__attribute__((weak))
905ssize_t writev(int fd, const struct iovec *iov, int iovcnt)
906{
907 int i;
908 ssize_t size_sum;
909
910 size_sum = 0;
911 for (i = 0; i < iovcnt; i += 1)
912 {
913 ssize_t size_cur;
914
915 size_cur = write(fd, iov[i].iov_base, iov[i].iov_len);
916 if (size_cur < 0)
917 return size_cur;
918 size_sum += size_cur;
919 if (size_cur != iov[i].iov_len)
920 break;
921 }
922 return size_sum;
923}
924#endif
925
926#ifdef F_truncate
927int truncate(const char *path, off_t length)
928{
929 ssize_t bytes_read;
930 int fd, res;
931 char buff[length];
932
933 fd = open(path, O_RDONLY);
934 if (fd < 0) {
935 errno = ENOENT;
936 return -1;
937 }
938
939 bytes_read = read(fd, &buff, length);
940 close(fd);
941 if (bytes_read < length) {
942 errno = EFBIG;
943 return -1;
944 }
945
946 fd = open (path, O_TRUNC|O_WRONLY);
947 if (fd < 0) {
948 errno = ENOENT;
949 return -1;
950 }
951
952 res = write(fd, &buff, length);
953 close(fd);
954 return res;
955}
956#endif
957
958#ifdef F_ftruncate
959int ftruncate(int fd, off_t length)
960{
961 errno = ENOSYS;
962 return -1; /* not supported */
963}
964#endif
965
966#ifdef F__symlink
967int _symlink(const char *target, const char *linkpath)
968{
969 char dest_target[MAXNAMLEN + 1];
970 char dest_linkpath[MAXNAMLEN + 1];
971
972 if(__path_absolute(target, dest_target, MAXNAMLEN) < 0) {
973 errno = ENAMETOOLONG;
974 return -1;
975 }
976
977 if(__path_absolute(linkpath, dest_linkpath, MAXNAMLEN) < 0) {
978 errno = ENAMETOOLONG;
979 return -1;
980 }
981
982 if (_libcglue_fdman_path_ops == NULL || _libcglue_fdman_path_ops->symlink == NULL)
983 {
984 errno = ENOSYS;
985 return -1;
986 }
987
988 return __transform_errno(_libcglue_fdman_path_ops->symlink(dest_target, dest_linkpath));
989}
990#else
991int _symlink(const char *target, const char *linkpath);
992#endif
993
994#ifdef F_symlink
995int symlink(const char *target, const char *linkpath)
996{
997 return _symlink(target, linkpath);
998}
999#endif
1000
1001#ifdef F__readlink
1002ssize_t _readlink(const char *path, char *buf, size_t bufsiz)
1003{
1004 char dest[MAXNAMLEN + 1];
1005
1006 if(__path_absolute(path, dest, MAXNAMLEN) < 0) {
1007 errno = ENAMETOOLONG;
1008 return -1;
1009 }
1010
1011 if (_libcglue_fdman_path_ops == NULL || _libcglue_fdman_path_ops->readlink == NULL)
1012 {
1013 errno = ENOSYS;
1014 return -1;
1015 }
1016
1017 return __transform_errno(_libcglue_fdman_path_ops->readlink(dest, buf, bufsiz));
1018}
1019#else
1020ssize_t _readlink(const char *path, char *buf, size_t bufsiz);
1021#endif
1022
1023#ifdef F_readlink
1024ssize_t readlink(const char *path, char *buf, size_t bufsiz)
1025{
1026 return _readlink(path, buf, bufsiz);
1027}
1028#endif
1029
1030#ifdef F_utime
1031int utime(const char *pathname, const struct utimbuf *times)
1032{
1033 // TODO: implement in terms of chstat
1034 errno = ENOSYS;
1035 return -1; /* not supported */
1036}
1037#endif
1038
1039#ifdef F_utimes
1040int utimes(const char *filename, const struct timeval times[2])
1041{
1042 // TODO: implement in terms of chstat
1043 errno = ENOSYS;
1044 return -1; /* not supported */
1045}
1046#endif
1047
1048#ifdef F_fchown
1049int fchown(int fd, uid_t owner, gid_t group)
1050{
1051 errno = ENOSYS;
1052 return -1; /* not supported */
1053}
1054#endif
1055
1056#ifdef F_getrandom
1057ssize_t getrandom(void *buf, size_t buflen, unsigned int flags)
1058{
1059 (void)flags;
1060
1061 arc4random_buf(buf, buflen);
1062 return buflen;
1063}
1064#endif
1065
1066#ifdef F__getentropy
1067// Called from newlib getentropyr.c
1068int _getentropy(void *buf, size_t buflen)
1069{
1070 u8 *buf_cur = buf;
1071 int i;
1072 // Restrict buffer size as documented in the man page
1073 if (buflen > 256)
1074 {
1075 errno = EIO;
1076 return -1;
1077 }
1078 // TODO: get proper entropy from e.g.
1079 // * RTC
1080 // * uninitialized memory
1081 // * Mechacon temperature
1082 for (i = 0; i < buflen; i += 1)
1083 {
1084 // Performance counter low buts should be changed for each call to cpu_ticks
1085 buf_cur[i] = (u8)(cpu_ticks() & 0xff);
1086 }
1087 return 0;
1088}
1089#endif
1090
1091#ifdef F_umask
1092mode_t umask(mode_t mask)
1093{
1094 return 0;
1095}
1096#endif
1097
1098#ifdef F_chmod
1099int chmod(const char *pathname, mode_t mode)
1100{
1101 errno = ENOSYS;
1102 return -1; /* not supported */
1103}
1104#endif
1105
1106#ifdef F_fchmod
1107int fchmod(int fd, mode_t mode)
1108{
1109 errno = ENOSYS;
1110 return -1; /* not supported */
1111}
1112#endif
1113
1114#ifdef F__chown
1115int _chown(const char *path, uid_t owner, gid_t group)
1116{
1117 errno = ENOSYS;
1118 return -1; /* not supported */
1119}
1120#else
1121int _chown(const char *path, uid_t owner, gid_t group);
1122#endif
1123
1124#ifdef F_chown
1125int chown(const char *path, uid_t owner, gid_t group)
1126{
1127 return _chown(path, owner, group);
1128}
1129#endif
1130
1131#ifdef F_pathconf
1132long pathconf(const char *path, int name)
1133{
1134 errno = ENOSYS;
1135 return -1; /* not supported */
1136}
1137#endif
1138
1139#ifdef F_fpathconf
1140long fpathconf(int fd, int name)
1141{
1142 errno = ENOSYS;
1143 return -1; /* not supported */
1144}
1145#endif
1146
1147#ifdef F_fsync
1148int fsync(int fd) {
1149 // TODO: implement in terms of sync
1150 return 0;
1151}
1152#endif
1153
1154#ifdef F_sysconf
1155long sysconf(int name)
1156{
1157 errno = EINVAL;
1158 return -1;
1159}
1160#endif
1161
1162#ifdef F_tcgetattr
1163int tcgetattr(int fd, struct termios *tp)
1164{
1165 errno = ENOSYS;
1166 return -1;
1167}
1168#endif
1169
1170#ifdef F_tcsetattr
1171int tcsetattr(int fd, int opts, const struct termios *tp)
1172{
1173 errno = ENOSYS;
1174 return -1;
1175}
1176#endif
1177
1178#ifdef F_getlogin
1179// Called from newlib glob.c
1180char *getlogin(void)
1181{
1182 return __dummy_passwd.pw_name;
1183}
1184#endif
1185
1186#ifdef F_getuid
1187// Called from newlib glob.c
1188uid_t getuid(void)
1189{
1190 return __dummy_passwd.pw_uid;
1191}
1192#endif
1193
1194#ifdef F_geteuid
1195uid_t geteuid(void)
1196{
1197 return __dummy_passwd.pw_uid;
1198}
1199#endif
1200
1201#ifdef F_getgid
1202gid_t getgid(void)
1203{
1204 return __dummy_passwd.pw_gid;
1205}
1206#endif
1207
1208#ifdef F_getegid
1209gid_t getegid(void)
1210{
1211 return __dummy_passwd.pw_gid;
1212}
1213#endif
1214
1215#ifdef F_getpwuid
1216// Called from newlib glob.c
1217struct passwd *getpwuid(uid_t uid) {
1218 /* There's no support for users */
1219 return &__dummy_passwd;
1220}
1221#endif
1222
1223#ifdef F_getpwnam
1224// Called from newlib glob.c
1225struct passwd *getpwnam(const char *name) {
1226 /* There's no support for users */
1227 return &__dummy_passwd;
1228}
1229#endif
1230
1231#ifdef F_issetugid
1232// Called from newlib glob.c
1233int issetugid(void)
1234{
1235 return 0;
1236}
1237#endif
1238
1239#ifdef F_getgrgid
1240struct group *getgrgid(gid_t gid)
1241{
1242 return &__dummy_group;
1243}
1244#endif
1245
1246#ifdef F_getgrnam
1247struct group *getgrnam(const char *nam)
1248{
1249 return &__dummy_group;
1250}
1251#endif
1252
1253#ifdef F_libcglue_get_fd_info
1254_libcglue_fdman_fd_info_t *libcglue_get_fd_info(int fd) {
1255 if (!__IS_FD_VALID(fd)) {
1256 errno = EBADF;
1257 return NULL;
1258 }
1259
1260 return &(__descriptormap[fd]->info);
1261}
1262#endif
1263
1264#ifdef F_ps2sdk_get_iop_fd
1265int ps2sdk_get_iop_fd(int fd)
1266{
1268 fdinfo = libcglue_get_fd_info(fd);
1269 if (fdinfo == NULL)
1270 {
1271 return -EBADF;
1272 }
1273 if (fdinfo->ops == NULL || fdinfo->ops->getfd == NULL)
1274 {
1275 return -ENOSYS;
1276 }
1277 return fdinfo->ops->getfd(fdinfo->userdata);
1278}
1279#endif
1280
1281#ifdef F_ps2sdk_get_iop_filename
1282char *ps2sdk_get_iop_filename(int fd)
1283{
1285 fdinfo = libcglue_get_fd_info(fd);
1286 if (fdinfo == NULL)
1287 {
1288 return NULL;
1289 }
1290 if (fdinfo->ops == NULL || fdinfo->ops->getfilename == NULL)
1291 {
1292 return NULL;
1293 }
1294 return fdinfo->ops->getfilename(fdinfo->userdata);
1295}
1296#endif
1297
1298#ifdef F__ps2sdk_close
1299int _ps2sdk_close(int fd)
1300{
1302 fdinfo = libcglue_get_fd_info(fd);
1303 if (fdinfo == NULL)
1304 {
1305 return -EBADF;
1306 }
1307 if (fdinfo->ops == NULL || fdinfo->ops->close == NULL)
1308 {
1309 return -ENOSYS;
1310 }
1311 return fdinfo->ops->close(fdinfo->userdata);
1312}
1313#endif
1314
1315#ifdef F__ps2sdk_dclose
1316int _ps2sdk_dclose(int fd)
1317{
1318 return _ps2sdk_close(fd);
1319}
1320#endif
1321
1322#ifdef F__ps2sdk_read
1323int _ps2sdk_read(int fd, void *buf, int nbytes)
1324{
1326 fdinfo = libcglue_get_fd_info(fd);
1327 if (fdinfo == NULL)
1328 {
1329 return -EBADF;
1330 }
1331 if (fdinfo->ops == NULL || fdinfo->ops->read == NULL)
1332 {
1333 return -ENOSYS;
1334 }
1335 return fdinfo->ops->read(fdinfo->userdata, buf, nbytes);
1336}
1337#endif
1338
1339#ifdef F__ps2sdk_lseek
1340int _ps2sdk_lseek(int fd, int offset, int whence)
1341{
1343 fdinfo = libcglue_get_fd_info(fd);
1344 if (fdinfo == NULL)
1345 {
1346 return -EBADF;
1347 }
1348 if (fdinfo->ops == NULL || fdinfo->ops->lseek == NULL)
1349 {
1350 return -ENOSYS;
1351 }
1352 return fdinfo->ops->lseek(fdinfo->userdata, offset, whence);
1353}
1354#endif
1355
1356#ifdef F__ps2sdk_lseek64
1357int64_t _ps2sdk_lseek64(int fd, int64_t offset, int whence)
1358{
1360 fdinfo = libcglue_get_fd_info(fd);
1361 if (fdinfo == NULL)
1362 {
1363 return -EBADF;
1364 }
1365 if (fdinfo->ops == NULL || fdinfo->ops->lseek64 == NULL)
1366 {
1367 return -ENOSYS;
1368 }
1369 return fdinfo->ops->lseek64(fdinfo->userdata, offset, whence);
1370}
1371#endif
1372
1373#ifdef F__ps2sdk_write
1374int _ps2sdk_write(int fd, const void *buf, int nbytes)
1375{
1377 fdinfo = libcglue_get_fd_info(fd);
1378 if (fdinfo == NULL)
1379 {
1380 return -EBADF;
1381 }
1382 if (fdinfo->ops == NULL || fdinfo->ops->write == NULL)
1383 {
1384 return -ENOSYS;
1385 }
1386 return fdinfo->ops->write(fdinfo->userdata, buf, nbytes);
1387}
1388#endif
1389
1390#ifdef F__ps2sdk_ioctl
1391int _ps2sdk_ioctl(int fd, int request, void *data)
1392{
1394 fdinfo = libcglue_get_fd_info(fd);
1395 if (fdinfo == NULL)
1396 {
1397 return -EBADF;
1398 }
1399 if (fdinfo->ops == NULL || fdinfo->ops->ioctl == NULL)
1400 {
1401 return -ENOSYS;
1402 }
1403 return fdinfo->ops->ioctl(fdinfo->userdata, request, data);
1404}
1405#endif
1406
1407#ifdef F__ps2sdk_ioctl2
1408int _ps2sdk_ioctl2(int fd, int request, void *arg, unsigned int arglen, void *buf, unsigned int buflen)
1409{
1411 fdinfo = libcglue_get_fd_info(fd);
1412 if (fdinfo == NULL)
1413 {
1414 return -EBADF;
1415 }
1416 if (fdinfo->ops == NULL || fdinfo->ops->ioctl == NULL)
1417 {
1418 return -ENOSYS;
1419 }
1420 return fdinfo->ops->ioctl2(fdinfo->userdata, request, arg, arglen, buf, buflen);
1421}
1422#endif
1423
1424#ifdef F__ps2sdk_dread
1425int _ps2sdk_dread(int fd, struct dirent *dir)
1426{
1428 fdinfo = libcglue_get_fd_info(fd);
1429 if (fdinfo == NULL)
1430 {
1431 return -EBADF;
1432 }
1433 if (fdinfo->ops == NULL || fdinfo->ops->dread == NULL)
1434 {
1435 return -ENOSYS;
1436 }
1437 return fdinfo->ops->dread(fdinfo->userdata, dir);
1438}
1439#endif
1440
1441/* ATFILE functions */
1442
1443#ifdef F_openat
1444int openat(int dirfd, const char *pathname, int flags, ...)
1445{
1446 // TODO: Do better implementation following https://linux.die.net/man/2/openat
1447 // for now use the same as open
1448
1449 // Extract mode from variable arguments
1450 va_list args;
1451 va_start(args, flags);
1452
1453 // Get the mode argument
1454 int mode = va_arg(args, int);
1455
1456 // Clean up the va_list
1457 va_end(args);
1458 return open(pathname, flags, mode);
1459}
1460#endif /* F_openat */
1461
1462#ifdef F_renameat
1463int renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath)
1464{
1465 // TODO: Do better implementation following https://linux.die.net/man/2/renameat
1466 // for now use the same as rename
1467 return rename(oldpath, newpath);
1468}
1469#endif /* F_renameat */
1470
1471#ifdef F_fchmodat
1472int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags)
1473{
1474 // TODO: Do better implementation following https://linux.die.net/man/2/fchmodat
1475 // for now use the same as chmod
1476 return chmod(pathname, mode);
1477}
1478#endif /* F_fchmodat */
1479
1480#ifdef F_fstatat
1481int fstatat(int dirfd, const char *pathname, struct stat *buf, int flags)
1482{
1483 // TODO: Do better implementation following https://linux.die.net/man/2/fstatat
1484 // for now use the same as stat
1485 return stat(pathname, buf);
1486}
1487#endif /* F_fstatat */
1488
1489#ifdef F_mkdirat
1490int mkdirat(int dirfd, const char *pathname, mode_t mode)
1491{
1492 // TODO: Do better implementation following https://linux.die.net/man/2/mkdirat
1493 // for now use the same as mkdir
1494 return mkdir(pathname, mode);
1495}
1496#endif /* F_mkdirat */
1497
1498#ifdef F_faccessat
1499int faccessat(int dirfd, const char *pathname, int mode, int flags)
1500{
1501 // TODO: Do better implementation following https://linux.die.net/man/2/faccessat
1502 // for now use the same as access
1503 return access(pathname, mode);
1504}
1505#endif /* F_faccessat */
1506
1507#ifdef F_fchownat
1508int fchownat(int dirfd, const char *pathname, uid_t owner, gid_t group, int flags)
1509{
1510 // TODO: Do better implementation following https://linux.die.net/man/2/fchownat
1511 // for now use the same as chown
1512 return chown(pathname, owner, group);
1513}
1514#endif /* F_fchownat */
1515
1516#ifdef F_linkat
1517int linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, int flags) {
1518 // TODO: Do better implementation following https://linux.die.net/man/2/linkat
1519 // for now use the same as link
1520 return link(oldpath, newpath);
1521}
1522#endif /* F_linkat */
1523
1524#ifdef F_readlinkat
1525int readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz)
1526{
1527 // TODO: Do better implementation following https://linux.die.net/man/2/linkat
1528 // for now use the same as readlink
1529 return readlink(pathname, buf, bufsiz);
1530}
1531#endif /* F_readlinkat */
1532
1533#ifdef F_unlinkat
1534int unlinkat(int dirfd, const char *pathname, int flags)
1535{
1536 // If flags contains AT_REMOVEDIR, then the path refers to a directory.
1537 // Otherwise, the path refers to a file.
1538 if (flags & AT_REMOVEDIR) {
1539 return rmdir(pathname);
1540 }
1541 else {
1542 return unlink(pathname);
1543 }
1544}
1545#endif /* F_unlinkat */
1546
1547#ifdef F_dup
1548int dup(int oldfd)
1549{
1550 if (!__IS_FD_VALID(oldfd)) {
1551 errno = EBADF;
1552 return -1;
1553 }
1554
1555 return __fdman_get_dup_descriptor(oldfd);
1556}
1557#endif /* F_dup */
1558
1559#ifdef F_dup2
1560// Called from wordexp.c, popen.c
1561int dup2(int oldfd, int newfd)
1562{
1563 if (!__IS_FD_VALID(oldfd)) {
1564 errno = EBADF;
1565 return -1;
1566 }
1567
1568 if (oldfd == newfd) {
1569 return oldfd;
1570 }
1571 if (newfd < 0) {
1572 errno = EBADF;
1573 return -1;
1574 }
1575 if (__descriptormap[newfd]) {
1576 close(newfd);
1577 }
1578 return __fdman_get_dup2_descriptor(oldfd, newfd);
1579}
1580#endif /* F_dup2 */
#define ENOENT
Definition errno.h:23
#define EINVAL
Definition errno.h:63
#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 uio.h:24
Definition time.h:29
u32 count
start sector of fragmented bd/file