summaryrefslogtreecommitdiff
path: root/devel/psptoolchain-newlib/files/patch-newlib-libc-sys-psp-libcglue.c
diff options
context:
space:
mode:
Diffstat (limited to 'devel/psptoolchain-newlib/files/patch-newlib-libc-sys-psp-libcglue.c')
-rw-r--r--devel/psptoolchain-newlib/files/patch-newlib-libc-sys-psp-libcglue.c939
1 files changed, 939 insertions, 0 deletions
diff --git a/devel/psptoolchain-newlib/files/patch-newlib-libc-sys-psp-libcglue.c b/devel/psptoolchain-newlib/files/patch-newlib-libc-sys-psp-libcglue.c
new file mode 100644
index 000000000000..2985d2966342
--- /dev/null
+++ b/devel/psptoolchain-newlib/files/patch-newlib-libc-sys-psp-libcglue.c
@@ -0,0 +1,939 @@
+--- newlib/libc/sys/psp/libcglue.c.orig 1970-01-01 02:00:00.000000000 +0200
++++ newlib/libc/sys/psp/libcglue.c 2007-06-01 12:22:26.000000000 +0300
+@@ -0,0 +1,936 @@
++/*
++ * PSP Software Development Kit - http://www.pspdev.org
++ * -----------------------------------------------------------------------
++ * Licensed under the BSD license, see LICENSE in PSPSDK root for details.
++ *
++ * libcglue.c - Newlib-compatible system calls.
++ *
++ * Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
++ * Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
++ * Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
++ * Copyright (c) 2005 Jim Paris <jim@jtan.com>
++ *
++ */
++#include <errno.h>
++#include <malloc.h>
++#include <reent.h>
++#include <stdarg.h>
++#include <stdlib.h>
++#include <string.h>
++#include <time.h>
++#include <sys/fcntl.h>
++#include <sys/stat.h>
++#include <sys/time.h>
++#include <sys/types.h>
++#include <sys/unistd.h>
++#include <sys/dirent.h>
++#include <sys/socket.h>
++
++#include <psptypes.h>
++#include <pspiofilemgr.h>
++#include <pspmodulemgr.h>
++#include <pspsysmem.h>
++#include <pspthreadman.h>
++#include <psputils.h>
++#include <psputility.h>
++#include <pspstdio.h>
++#include <pspintrman.h>
++#include "fdman.h"
++
++extern char __psp_cwd[MAXPATHLEN + 1];
++extern void __psp_init_cwd(char *argv_0);
++extern int __psp_path_absolute(const char *in, char *out, int len);
++extern int pspDisableInterrupts();
++extern void pspEnableInterrupts(int);
++
++/* The following functions are defined in socket.c. They have weak linkage so
++ that the user doesn't have to link against the PSP network libraries if they
++ don't use the sockets API. */
++extern int __psp_socket_close(int s) __attribute__((weak));
++extern ssize_t __psp_socket_recv(int s, void *buf, size_t len, int flags) __attribute__((weak));
++extern ssize_t __psp_socket_send(int s, const void *buf, size_t len, int flags) __attribute__((weak));
++
++extern int pipe(int fildes[2]);
++extern int __psp_pipe_close(int filedes);
++extern int __psp_pipe_nonblocking_read(int fd, void *buf, size_t len);
++extern int __psp_pipe_read(int fd, void *buf, size_t len);
++extern int __psp_pipe_write(int fd, const void *buf, size_t size);
++extern int __psp_pipe_nonblocking_write(int fd, const void *buf, size_t len);
++
++int __psp_set_errno(int code);
++
++#ifdef F___psp_set_errno
++int __psp_set_errno(int code)
++{
++ if ((code & 0x80010000) == 0x80010000) {
++ errno = code & 0xFFFF;
++ return -1;
++ }
++ return code;
++}
++#endif
++
++#ifdef F_getcwd
++char *getcwd(char *buf, size_t size)
++{
++ if(!buf) {
++ errno = EINVAL;
++ return NULL;
++ }
++
++ if(strlen(__psp_cwd) >= size) {
++ errno = ERANGE;
++ return NULL;
++ }
++
++ strcpy(buf, __psp_cwd);
++ return buf;
++}
++#endif
++
++#ifdef F_chdir
++int chdir(const char *path)
++{
++ char dest[MAXPATHLEN + 1];
++ SceUID uid;
++
++ if(__psp_path_absolute(path, dest, MAXPATHLEN) < 0) {
++ errno = ENAMETOOLONG;
++ return -1;
++ }
++
++ /* sceIoChdir doesn't give an indication of whether it worked,
++ so test for existence by attempting to open the dir */
++ uid = sceIoDopen(dest);
++ if(uid < 0) {
++ errno = ENOTDIR;
++ return -1;
++ }
++ sceIoDclose(uid);
++
++ sceIoChdir(dest);
++ strcpy(__psp_cwd, dest);
++ return 0;
++}
++#endif
++
++#ifdef F_mkdir
++int mkdir(const char *pathname, mode_t mode)
++{
++ char dest[MAXPATHLEN + 1];
++
++ if(__psp_path_absolute(pathname, dest, MAXPATHLEN) < 0) {
++ errno = ENAMETOOLONG;
++ return -1;
++ }
++
++ return __psp_set_errno(sceIoMkdir(dest, mode));
++}
++#endif
++
++#ifdef F_rmdir
++int rmdir(const char *pathname)
++{
++ char dest[MAXPATHLEN + 1];
++
++ if(__psp_path_absolute(pathname, dest, MAXPATHLEN) < 0) {
++ errno = ENAMETOOLONG;
++ return -1;
++ }
++
++ return __psp_set_errno(sceIoRmdir(dest));
++}
++#endif
++
++#ifdef F_realpath
++char *realpath(const char *path, char *resolved_path)
++{
++ if(!path || !resolved_path) {
++ errno = EINVAL;
++ return NULL;
++ }
++ if(__psp_path_absolute(path, resolved_path, MAXPATHLEN) < 0) {
++ errno = ENAMETOOLONG;
++ return NULL;
++ }
++ if(access(resolved_path, F_OK) < 0) {
++ errno = ENOENT;
++ return NULL;
++ }
++ return resolved_path;
++}
++#endif
++
++/* Wrappers of the standard open(), close(), read(), write(), unlink() and lseek() routines. */
++#ifdef F__open
++int _open(const char *name, int flags, int mode)
++{
++ int scefd, fd;
++ int sce_flags;
++ char dest[MAXPATHLEN + 1];
++
++ if(__psp_path_absolute(name, dest, MAXPATHLEN) < 0) {
++ errno = ENAMETOOLONG;
++ return -1;
++ }
++
++ /* O_RDONLY starts at 0, where PSP_O_RDONLY starts at 1, so remap the read/write
++ flags by adding 1. */
++ sce_flags = (flags & O_ACCMODE) + 1;
++
++ /* Translate standard open flags into the flags understood by the PSP kernel. */
++ if (flags & O_APPEND) {
++ sce_flags |= PSP_O_APPEND;
++ }
++ if (flags & O_CREAT) {
++ sce_flags |= PSP_O_CREAT;
++ }
++ if (flags & O_TRUNC) {
++ sce_flags |= PSP_O_TRUNC;
++ }
++ if (flags & O_EXCL) {
++ sce_flags |= PSP_O_EXCL;
++ }
++ if (flags & O_NONBLOCK) {
++ sce_flags |= PSP_O_NBLOCK;
++ }
++
++ scefd = sceIoOpen(dest, sce_flags, mode);
++ if (scefd >= 0) {
++ fd = __psp_fdman_get_new_descriptor();
++ if (fd != -1) {
++ __psp_descriptormap[fd]->sce_descriptor = scefd;
++ __psp_descriptormap[fd]->type = __PSP_DESCRIPTOR_TYPE_FILE;
++ __psp_descriptormap[fd]->flags = flags;
++ __psp_descriptormap[fd]->filename = strdup(dest);
++ return fd;
++ }
++ else {
++ sceIoClose(scefd);
++ errno = ENOMEM;
++ return -1;
++ }
++ }
++ else {
++ return __psp_set_errno(scefd);
++ }
++
++}
++#endif
++
++#ifdef F__close
++int _close(int fd)
++{
++ int ret = 0;
++
++ if (!__PSP_IS_FD_VALID(fd)) {
++ errno = EBADF;
++ return -1;
++ }
++
++ switch(__psp_descriptormap[fd]->type)
++ {
++ case __PSP_DESCRIPTOR_TYPE_FILE:
++ case __PSP_DESCRIPTOR_TYPE_TTY:
++ if (__psp_descriptormap[fd]->ref_count == 1) {
++ ret = __psp_set_errno(sceIoClose(__psp_descriptormap[fd]->sce_descriptor));
++ }
++ __psp_fdman_release_descriptor(fd);
++ return ret;
++ break;
++ case __PSP_DESCRIPTOR_TYPE_PIPE:
++ return __psp_pipe_close(fd);
++ break;
++ case __PSP_DESCRIPTOR_TYPE_SOCKET:
++ if (__psp_socket_close != NULL) {
++ ret = __psp_socket_close(fd);
++ return ret;
++ }
++ break;
++ default:
++ break;
++ }
++
++ errno = EBADF;
++ return -1;
++}
++#endif
++
++#ifdef F__read
++int _read(int fd, void *buf, size_t size)
++{
++ if (!__PSP_IS_FD_VALID(fd)) {
++ errno = EBADF;
++ return -1;
++ }
++
++ switch(__psp_descriptormap[fd]->type)
++ {
++ case __PSP_DESCRIPTOR_TYPE_FILE:
++ case __PSP_DESCRIPTOR_TYPE_TTY:
++ return __psp_set_errno(sceIoRead(__psp_descriptormap[fd]->sce_descriptor, buf, size));
++ break;
++ case __PSP_DESCRIPTOR_TYPE_PIPE:
++ if (__psp_descriptormap[fd]->flags & O_NONBLOCK) {
++ return __psp_pipe_nonblocking_read(fd, buf, size);
++ }
++ else {
++ return __psp_pipe_read(fd, buf, size);
++ }
++ break;
++ case __PSP_DESCRIPTOR_TYPE_SOCKET:
++ if (__psp_socket_recv != NULL) {
++ return __psp_socket_recv(fd, buf, size, 0);
++ }
++ break;
++ default:
++ break;
++ }
++
++ errno = EBADF;
++ return -1;
++
++}
++#endif
++
++#ifdef F__write
++int _write(int fd, const void *buf, size_t size)
++{
++ if (!__PSP_IS_FD_VALID(fd)) {
++ errno = EBADF;
++ return -1;
++ }
++
++ switch(__psp_descriptormap[fd]->type)
++ {
++ case __PSP_DESCRIPTOR_TYPE_FILE:
++ case __PSP_DESCRIPTOR_TYPE_TTY:
++ return __psp_set_errno(sceIoWrite(__psp_descriptormap[fd]->sce_descriptor, buf, size));
++ break;
++ case __PSP_DESCRIPTOR_TYPE_PIPE:
++ if (__psp_descriptormap[fd]->flags & O_NONBLOCK) {
++ return __psp_pipe_nonblocking_write(fd, buf, size);
++ }
++ else {
++ return __psp_pipe_write(fd, buf, size);
++ }
++ break;
++ break;
++ case __PSP_DESCRIPTOR_TYPE_SOCKET:
++ if (__psp_socket_send != NULL) {
++ return __psp_socket_send(fd, buf, size, 0);
++ }
++ break;
++ default:
++ break;
++ }
++
++ errno = EBADF;
++ return -1;
++}
++#endif
++
++#ifdef F__lseek
++off_t _lseek(int fd, off_t offset, int whence)
++{
++ if (!__PSP_IS_FD_VALID(fd)) {
++ errno = EBADF;
++ return -1;
++ }
++
++ switch(__psp_descriptormap[fd]->type)
++ {
++ case __PSP_DESCRIPTOR_TYPE_FILE:
++ /* We don't have to do anything with the whence argument because SEEK_* == PSP_SEEK_*. */
++ return (off_t) __psp_set_errno(sceIoLseek(__psp_descriptormap[fd]->sce_descriptor, offset, whence));
++ break;
++ case __PSP_DESCRIPTOR_TYPE_PIPE:
++ break;
++ case __PSP_DESCRIPTOR_TYPE_SOCKET:
++ break;
++ default:
++ break;
++ }
++
++ errno = EBADF;
++ return -1;
++
++}
++#endif
++
++#ifdef F__unlink
++int _unlink(const char *path)
++{
++ char dest[MAXPATHLEN + 1];
++
++ if(__psp_path_absolute(path, dest, MAXPATHLEN) < 0) {
++ errno = ENAMETOOLONG;
++ return -1;
++ }
++
++ return __psp_set_errno(sceIoRemove(dest));
++}
++#endif
++
++#ifdef F__link
++int _link(const char *name1, const char *name2)
++{
++ errno = ENOSYS;
++ return -1; /* not supported */
++}
++#endif
++
++#ifdef F_opendir
++DIR *opendir(const char *filename)
++{
++ char dest[MAXPATHLEN + 1];
++ DIR *dirp;
++ SceUID uid;
++
++ /* Normalize pathname so that opendir(".") works */
++ if(__psp_path_absolute(filename, dest, MAXPATHLEN) < 0) {
++ errno = ENOENT;
++ return NULL;
++ }
++
++ dirp = (DIR *)malloc(sizeof(DIR));
++
++ uid = sceIoDopen(dest);
++
++ if (uid < 0)
++ {
++ free(dirp);
++ (void) __psp_set_errno(uid);
++ return NULL;
++ }
++
++ dirp->uid = uid;
++
++ return dirp;
++}
++#endif
++
++#ifdef F_readdir
++struct dirent *readdir(DIR *dirp)
++{
++ int ret;
++
++ /* Zero the dirent, to avoid possible problems with sceIoDread */
++ memset(&dirp->de, 0, sizeof(struct dirent));
++
++ ret = sceIoDread(dirp->uid, (SceIoDirent *)&dirp->de);
++ if (ret == 0) {
++ /* EOF */
++ errno = 0;
++ return NULL;
++ }
++ if (ret < 0) {
++ (void) __psp_set_errno(ret);
++ return NULL;
++ }
++
++ return &dirp->de;
++}
++#endif
++
++#ifdef F_closedir
++int closedir(DIR *dirp)
++{
++ if (dirp != NULL)
++ {
++ int uid;
++ uid = dirp->uid;
++ free (dirp);
++ return __psp_set_errno(sceIoDclose(uid));
++ }
++ errno = EBADF;
++ return -1;
++}
++#endif
++
++/* Time routines. These wrap around the routines provided by the kernel. */
++#ifdef F__gettimeofday
++int _gettimeofday(struct timeval *tp, struct timezone *tzp)
++{
++ return __psp_set_errno(sceKernelLibcGettimeofday(tp, tzp));
++}
++
++#endif
++
++#if defined(F_clock)
++clock_t clock(void)
++{
++ return sceKernelLibcClock();
++}
++#endif
++
++#if defined(F_time)
++time_t time(time_t *t)
++{
++ return __psp_set_errno(sceKernelLibcTime(t));
++}
++#endif
++
++#if defined(F_sleep)
++unsigned int sleep(unsigned int secs) {
++ while(secs--) {
++ sceKernelDelayThreadCB(1000000);
++ }
++ return 0;
++}
++#endif
++
++/* PSP-compatible sbrk(). */
++#if defined(F__sbrk) || defined(F_glue__sbrk)
++/* TODO: Currently our default heap is set to the maximum available block size
++ when sbrk() is first called. Sony seems to always use a default of 64KB,
++ with the expectation that user programs will override the default size with
++ their own desired size. The only reason I can think of them doing this is
++ to allow each PRX to have their own seperate heap. I think that their
++ method is overkill for most user programs.
++
++ What I'd like to do instead is to use the default of 64KB for PRXes as Sony
++ does, but use the maximum available block size for executables. This avoids
++ the requirement of specifying the heap size manually in user programs.
++ However, we currently don't have a clean way to distinguish PRXes and normal
++ executables, so this code needs to be revisited once we do come up with a
++ way. */
++#define DEFAULT_PRX_HEAP_SIZE_KB 64
++
++/* If defined it specifies the desired size of the heap, in KB. */
++extern unsigned int sce_newlib_heap_kb_size __attribute__((weak));
++extern int __pspsdk_is_prx __attribute__((weak));
++
++/* UID of the memory block that represents the heap. */
++static SceUID __psp_heap_blockid;
++
++void * _sbrk(ptrdiff_t incr)
++{
++ static void * heap_bottom = NULL;
++ static void * heap_top = NULL;
++ static void * heap_ptr = NULL;
++
++ /* Has our heap been initialized? */
++ if (heap_bottom == NULL) {
++ /* No, initialize the heap. */
++ SceSize heap_size;
++
++ if (&sce_newlib_heap_kb_size != NULL) {
++ heap_size = sce_newlib_heap_kb_size * 1024;
++ } else {
++ if (&__pspsdk_is_prx != NULL) {
++ heap_size = DEFAULT_PRX_HEAP_SIZE_KB * 1024;
++ } else {
++ heap_size = sceKernelMaxFreeMemSize();
++ }
++ }
++
++ __psp_heap_blockid = sceKernelAllocPartitionMemory(2, "block", PSP_SMEM_Low, heap_size, NULL);
++ if (__psp_heap_blockid > 0) {
++ heap_bottom = sceKernelGetBlockHeadAddr(__psp_heap_blockid);
++ heap_ptr = heap_bottom;
++ heap_top = (unsigned char *) heap_bottom + heap_size;
++ }
++ }
++
++ void * heap_addr = (void *) -1;
++ void * next_heap_ptr = (void *) ((ptrdiff_t) heap_ptr + incr);
++ if ((heap_bottom != NULL) && (next_heap_ptr >= heap_bottom) && (next_heap_ptr < heap_top)) {
++ heap_addr = heap_ptr;
++ heap_ptr = next_heap_ptr;
++ }
++
++ return heap_addr;
++}
++
++/* Free the heap. */
++int __psp_free_heap(void)
++{
++ if (__psp_heap_blockid > 0) {
++ return sceKernelFreePartitionMemory(__psp_heap_blockid);
++ }
++
++ return __psp_heap_blockid;
++}
++#endif
++
++/* Other POSIX routines that must be defined. */
++#ifdef F__fstat
++int _fstat(int fd, struct stat *sbuf)
++{
++ int ret;
++ SceOff oldpos;
++ if (!__PSP_IS_FD_VALID(fd)) {
++ errno = EBADF;
++ return -1;
++ }
++
++ switch(__psp_descriptormap[fd]->type)
++ {
++ case __PSP_DESCRIPTOR_TYPE_TTY:
++ memset(sbuf, '\0', sizeof(struct stat));
++ sbuf->st_mode = S_IFCHR;
++ return 0;
++ break;
++ case __PSP_DESCRIPTOR_TYPE_FILE:
++ if (__psp_descriptormap[fd]->filename != NULL) {
++ ret = stat(__psp_descriptormap[fd]->filename, sbuf);
++
++ /* Find true size of the open file */
++ oldpos = sceIoLseek(__psp_descriptormap[fd]->sce_descriptor, 0, SEEK_CUR);
++ if (oldpos != (off_t) -1) {
++ sbuf->st_size = (off_t) sceIoLseek(__psp_descriptormap[fd]->sce_descriptor, 0, SEEK_END);
++ sceIoLseek(__psp_descriptormap[fd]->sce_descriptor, oldpos, SEEK_SET);
++ }
++ return ret;
++ }
++ break;
++ case __PSP_DESCRIPTOR_TYPE_PIPE:
++ case __PSP_DESCRIPTOR_TYPE_SOCKET:
++ default:
++ break;
++ }
++
++ errno = EBADF;
++ return -1;
++}
++#endif
++
++#ifdef F_isatty
++int isatty(int fd)
++{
++ if (!__PSP_IS_FD_VALID(fd)) {
++ errno = EBADF;
++ return 0;
++ }
++
++ if (__psp_descriptormap[fd]->type == __PSP_DESCRIPTOR_TYPE_TTY) {
++ return 1;
++ }
++ else {
++ return 0;
++ }
++}
++#endif
++
++#ifdef F__stat
++static time_t psp_to_epoch_time(ScePspDateTime psp_time)
++{
++ struct tm conv_time;
++ conv_time.tm_year = psp_time.year;
++ conv_time.tm_mon = psp_time.month;
++ conv_time.tm_mday = psp_time.day;
++ conv_time.tm_hour = psp_time.hour;
++ conv_time.tm_min = psp_time.minute;
++ conv_time.tm_sec = psp_time.second;
++ conv_time.tm_isdst = -1;
++ return mktime(&conv_time);
++}
++
++int _stat(const char *filename, struct stat *buf)
++{
++ SceIoStat psp_stat;
++ char dest[MAXPATHLEN + 1];
++ int ret;
++
++ if(__psp_path_absolute(filename, dest, MAXPATHLEN) < 0) {
++ errno = ENAMETOOLONG;
++ return -1;
++ }
++
++ memset(buf, '\0', sizeof(struct stat));
++ ret = sceIoGetstat(dest, &psp_stat);
++ if (ret < 0) {
++ return __psp_set_errno(ret);
++ }
++
++ buf->st_ctime = psp_to_epoch_time(psp_stat.st_ctime);
++ buf->st_atime = psp_to_epoch_time(psp_stat.st_atime);
++ buf->st_mtime = psp_to_epoch_time(psp_stat.st_mtime);
++
++ buf->st_mode = (psp_stat.st_mode & 0xfff) |
++ ((FIO_S_ISLNK(psp_stat.st_mode))?(S_IFLNK):(0)) |
++ ((FIO_S_ISREG(psp_stat.st_mode))?(S_IFREG):(0)) |
++ ((FIO_S_ISDIR(psp_stat.st_mode))?(S_IFDIR):(0));
++ buf->st_size = psp_stat.st_size;
++ return 0;
++}
++#endif
++
++/* from stat.h in ps2sdk, this function may be correct */
++#define FIO_CST_SIZE 0x0004
++
++#ifdef F_truncate
++int truncate(const char *filename, off_t length)
++{
++ SceIoStat psp_stat;
++ char dest[MAXPATHLEN + 1];
++
++ if(__psp_path_absolute(filename, dest, MAXPATHLEN) < 0) {
++ errno = ENAMETOOLONG;
++ return -1;
++ }
++
++ psp_stat.st_size = length;
++ if(length < 0)
++ {
++ errno = EINVAL;
++ return -1;
++ }
++ return __psp_set_errno(sceIoChstat(dest, &psp_stat, FIO_CST_SIZE));
++}
++#endif
++
++/* Unsupported newlib system calls. */
++#ifdef F__fork
++pid_t fork(void)
++{
++ errno = ENOSYS;
++ return (pid_t) -1;
++}
++#endif
++
++#ifdef F__getpid
++pid_t _getpid(void)
++{
++ errno = ENOSYS;
++ return (pid_t) -1;
++}
++#endif
++
++#ifdef F__kill
++int _kill(int unused, int unused2)
++{
++ errno = ENOSYS;
++ return -1;
++}
++#endif
++
++#ifdef F__wait
++pid_t _wait(int *unused)
++{
++ errno = ENOSYS;
++ return (pid_t) -1;
++}
++#endif
++
++#ifdef F_access
++int access(const char *fn, int flags)
++{
++ struct stat s;
++ if (stat(fn, &s))
++ return -1;
++ if (s.st_mode & S_IFDIR)
++ return 0;
++ if (flags & W_OK)
++ {
++ if (s.st_mode & S_IWRITE)
++ return 0;
++ errno = EACCES;
++ return -1;
++ }
++ return 0;
++}
++#endif
++
++#ifdef F__fcntl
++int _fcntl(int fd, int cmd, ...)
++{
++ if (!__PSP_IS_FD_VALID(fd)) {
++ errno = EBADF;
++ return -1;
++ }
++
++ switch (cmd)
++ {
++ case F_DUPFD:
++ {
++ return __psp_fdman_get_dup_descriptor(fd);
++ break;
++ }
++ case F_GETFL:
++ {
++ return __psp_descriptormap[fd]->flags;
++ break;
++ }
++ case F_SETFL:
++ {
++ int newfl;
++ va_list args;
++
++ va_start (args, cmd); /* Initialize the argument list. */
++ newfl = va_arg(args, int);
++ va_end (args); /* Clean up. */
++
++ __psp_descriptormap[fd]->flags = newfl;
++
++ switch(__psp_descriptormap[fd]->type)
++ {
++ case __PSP_DESCRIPTOR_TYPE_FILE:
++ break;
++ case __PSP_DESCRIPTOR_TYPE_PIPE:
++ break;
++ case __PSP_DESCRIPTOR_TYPE_SOCKET:
++ if (newfl & O_NONBLOCK)
++ {
++ int one = 1;
++ return setsockopt(fd, SOL_SOCKET, SO_NONBLOCK, (char *)&one, sizeof(one));
++ }
++ else
++ {
++ int zero = 0;
++ return setsockopt(fd, SOL_SOCKET, SO_NONBLOCK, (char *)&zero, sizeof(zero));
++ }
++ break;
++ default:
++ break;
++ }
++ return 0;
++ break;
++ }
++ }
++
++ errno = EBADF;
++ return -1;
++}
++#endif /* F__fcntl */
++
++#ifdef F_tzset
++void tzset(void)
++{
++ static int initialized = 0;
++
++ if (!initialized)
++ {
++ initialized = 1;
++
++ /* Don't init if TZ has already been set once, this probably means the user
++ wanted to override what we would set below. */
++ if (getenv("TZ") == NULL)
++ {
++ /* Initialize timezone from PSP configuration */
++ int tzOffset = 0;
++ sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_TIMEZONE, &tzOffset);
++ int tzOffsetAbs = tzOffset < 0 ? -tzOffset : tzOffset;
++ int hours = tzOffsetAbs / 60;
++ int minutes = tzOffsetAbs - hours * 60;
++ int pspDaylight = 0;
++ sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_DAYLIGHTSAVINGS, &pspDaylight);
++ static char tz[18];
++ sprintf(tz, "GMT%s%02i:%02i%s", tzOffset < 0 ? "+" : "-", hours, minutes, pspDaylight ? "daylight" : "");
++ setenv("TZ", tz, 1);
++ }
++ }
++
++ _tzset_r(_REENT);
++}
++#endif
++
++#ifdef F_mlock
++static unsigned int lock_count = 0;
++static unsigned int intr_flags = 0;
++
++void __malloc_lock(struct _reent *ptr)
++{
++ unsigned int flags = pspDisableInterrupts();
++
++ if (lock_count == 0) {
++ intr_flags = flags;
++ }
++
++ lock_count++;
++}
++
++void __malloc_unlock(struct _reent *ptr)
++{
++ if (--lock_count == 0) {
++ pspEnableInterrupts(intr_flags);
++ }
++}
++#endif
++
++/* Exit. */
++#if defined(F__exit) || defined(F_glue__exit)
++extern int sce_newlib_nocreate_thread_in_start __attribute__((weak));
++
++extern int __psp_free_heap(void);
++
++void _exit(int status)
++{
++ if (&sce_newlib_nocreate_thread_in_start == NULL) {
++ /* Free the heap created by _sbrk(). */
++ __psp_free_heap();
++
++ sceKernelSelfStopUnloadModule(1, 0, NULL);
++ } else {
++ if (status == 0) {
++ /* Free the heap created by _sbrk(). */
++ __psp_free_heap();
++ }
++
++ sceKernelExitThread(status);
++ }
++
++ while (1) ;
++}
++
++/* Note: This function is being linked into _exit.o.
++
++ Because __psp_libc_init is a weak import in crt0.c, the linker
++ chooses to ignore an object file in libc.a that contains just this
++ function, since it's not necessary for successful compilation.
++
++ By putting it instead in _exit.o, which is already used by crt0.c,
++ the linker sees __psp_libc_init and resolves the symbol properly.
++*/
++void __psp_libc_init(int argc, char *argv[])
++{
++ (void) argc;
++
++ /* Initialize cwd from this program's path */
++ __psp_init_cwd(argv[0]);
++
++ /* Initialize filedescriptor management */
++ __psp_fdman_init();
++}
++
++#endif /* F__exit */
++
++#ifdef F__rename
++int _rename(const char *old, const char *new)
++{
++ char oldname[MAXPATHLEN + 1];
++ char newname[MAXPATHLEN + 1];
++
++ if(__psp_path_absolute(old, oldname, MAXPATHLEN) < 0) {
++ errno = ENAMETOOLONG;
++ return -1;
++ }
++
++ if(__psp_path_absolute(new, newname, MAXPATHLEN) < 0) {
++ errno = ENAMETOOLONG;
++ return -1;
++ }
++
++ return __psp_set_errno(sceIoRename(oldname, newname));
++}
++#endif
++
++#ifdef F_nanosleep
++/* note: we don't use rem as we have no signals */
++int nanosleep(const struct timespec *req, struct timespec *rem)
++{
++ if( req == NULL )
++ return EFAULT;
++
++ if( rem != NULL ) {
++ rem->tv_sec = 0;
++ rem->tv_nsec = 0;
++ }
++
++ sceKernelDelayThreadCB( 1000000 * req->tv_sec + (req->tv_nsec / 1000) );
++
++ return 0;
++}
++#endif
++