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