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