Changes include:
-File descriptor management: all file descriptors now come from a common pool. Things like the internal sce descriptor, reference count, filename, flags and descriptor type are kept track of here. This allows for things like: pipe(), socket() and open() to return three consecutive descriptors if called in order. This behavior is required for some applications, furthemore select() is expected to poll file descriptors smaller than FD_SETSIZE which is 256, and this was impossible using the native descriptors.
It also allows some of the code to be simplified, like no more socket file desctiptor masking, or TTY's filename indicator.. etc. And also for adding pipe support, which was my main goal, as both this applications, and I'm sure more, use pipes for thread synchronization/communication.
One thing that needs to be done here is add a locking mechanism to the "get new desciptor" call, to make it thread safe. ATM, is as safe as malloc(), I guess.
-Pipe support: the pipe(..) function, and read/write.
-fcntl support: the function is now implemented, and allows to set and get file descriptor flags. Implementation is not 100% complete. But socket's can be set to non-blocking mode via a fcntl call now. Also, file descriptors can be duplicated (with ref-counting so the real close is only called on the last fd's close). -- Now dup
-socket code simplified a bit thanks to the descriptor management. select() implementation removed, as it only worked with sockets.
-new select() implementation: this implementation is far from perfect, as it manually polls file descriptors internally. Timeout setting is accurate to the millisecond. And it supports pipes and sockets. Support for files is yet to be completed (not sure how to implement it yet).
It works fine for me right now. Compiled against PSPRadio, retawq and links. But I kindly ask for your review before I commit to subversion.
svn diff patch follows for your review:
Code: Select all
Index: libc/sys/psp/pspcwd.c
===================================================================
--- libc/sys/psp/pspcwd.c (revision 1866)
+++ libc/sys/psp/pspcwd.c (working copy)
@@ -19,7 +19,6 @@
#include <pspiofilemgr.h>
char __psp_cwd[MAXPATHLEN + 1] = { 0 };
-char * __psp_filename_map[1024];
/* Set the current working directory (CWD) to the path where the module was launched. */
void __psp_init_cwd(char *argv_0)
Index: libc/sys/psp/Makefile.in
===================================================================
--- libc/sys/psp/Makefile.in (revision 1866)
+++ libc/sys/psp/Makefile.in (working copy)
@@ -92,19 +92,26 @@
noinst_LIBRARIES = lib.a
-LIBCGLUE_MULT_OBJS = _close.o _exit.o _fork.o _fstat.o _getpid.o _gettimeofday.o _kill.o _lseek.o _open.o _read.o _sbrk.o _wait.o _write.o clock.o isatty.o time.o _link.o _unlink.o sleep.o opendir.o readdir.o closedir.o getcwd.o chdir.o mkdir.o rmdir.o realpath.o _stat.o truncate.o access.o tzset.o __psp_set_errno.o mlock.o
+LIBCGLUE_MULT_OBJS = _close.o _exit.o _fork.o _fstat.o _getpid.o _gettimeofday.o _kill.o _lseek.o _open.o _read.o _sbrk.o _wait.o _write.o clock.o isatty.o time.o _link.o _unlink.o sleep.o opendir.o readdir.o closedir.o getcwd.o chdir.o mkdir.o rmdir.o realpath.o _stat.o truncate.o access.o tzset.o __psp_set_errno.o mlock.o _fcntl.o
-SOCKET_MULT_OBJS = socket.o accept.o bind.o connect.o getsockopt.o listen.o recv.o recvfrom.o send.o sendto.o setsockopt.o shutdown.o __psp_socket_map.o getsockname.o getpeername.o select.o inet_ntoa.o
+SOCKET_MULT_OBJS = socket.o accept.o bind.o connect.o getsockopt.o listen.o recv.o recvfrom.o send.o sendto.o setsockopt.o shutdown.o getsockname.o getpeername.o inet_ntoa.o
+PIPE_OBJS = pipe.o
+
+FDMAN_OBJS = fdman.o
+
+SELECT_OBJS = select.o
+
XPRINTF_MULT_OBJS = vxprintf.o _xprintf.o __sout.o vsnprintf.o snprintf.o vsprintf.o sprintf.o __mout.o mprintf.o vmprintf.o asprintf.o vasprintf.o __fout.o fprintf.o vfprintf.o printf.o vprintf.o _sprintf_r.o
NETDB_MULT_OBJS = h_errno.o gethostbyaddr.o gethostbyname.o
-lib_a_SOURCES = libcglue.c socket.c pspcwd.c xprintf.c netdb.c
-lib_a_LIBADD = $(LIBCGLUE_MULT_OBJS) $(SOCKET_MULT_OBJS) $(XPRINTF_MULT_OBJS) $(NETDB_MULT_OBJS)
+lib_a_SOURCES = libcglue.c socket.c pspcwd.c xprintf.c netdb.c pipe.c fdman.c select.c
+lib_a_LIBADD = $(LIBCGLUE_MULT_OBJS) $(SOCKET_MULT_OBJS) $(XPRINTF_MULT_OBJS) $(NETDB_MULT_OBJS) $(PIPE_OBJS) $(FDMAN_OBJS) $(SELECT_OBJS)
+
ACLOCAL_AMFLAGS = -I ../../..
CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -120,15 +127,16 @@
_gettimeofday.o _kill.o _lseek.o _open.o _read.o _sbrk.o _wait.o \
_write.o clock.o isatty.o time.o _link.o _unlink.o sleep.o opendir.o \
readdir.o closedir.o getcwd.o chdir.o mkdir.o rmdir.o realpath.o \
-_stat.o truncate.o access.o tzset.o __psp_set_errno.o mlock.o socket.o \
-accept.o bind.o connect.o getsockopt.o listen.o recv.o recvfrom.o \
-send.o sendto.o setsockopt.o shutdown.o __psp_socket_map.o \
-getsockname.o getpeername.o select.o inet_ntoa.o vxprintf.o _xprintf.o \
-__sout.o vsnprintf.o snprintf.o vsprintf.o sprintf.o __mout.o mprintf.o \
-vmprintf.o asprintf.o vasprintf.o __fout.o fprintf.o vfprintf.o \
-printf.o vprintf.o _sprintf_r.o h_errno.o gethostbyaddr.o \
-gethostbyname.o
-lib_a_OBJECTS = libcglue.o socket.o pspcwd.o xprintf.o netdb.o
+_stat.o truncate.o access.o tzset.o __psp_set_errno.o mlock.o _fcntl.o \
+socket.o accept.o bind.o connect.o getsockopt.o listen.o recv.o \
+recvfrom.o send.o sendto.o setsockopt.o shutdown.o getsockname.o \
+getpeername.o inet_ntoa.o vxprintf.o _xprintf.o __sout.o vsnprintf.o \
+snprintf.o vsprintf.o sprintf.o __mout.o mprintf.o vmprintf.o \
+asprintf.o vasprintf.o __fout.o fprintf.o vfprintf.o printf.o vprintf.o \
+_sprintf_r.o h_errno.o gethostbyaddr.o gethostbyname.o pipe.o fdman.o \
+select.o
+lib_a_OBJECTS = libcglue.o socket.o pspcwd.o xprintf.o netdb.o pipe.o \
+fdman.o select.o
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
@@ -215,7 +223,7 @@
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
- || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP))
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
mostlyclean-tags:
@@ -362,6 +370,15 @@
$(NETDB_MULT_OBJS): netdb.c
$(COMPILE) -DF_$* $< -c -o $@
+$(PIPE_OBJS): pipe.c
+ $(COMPILE) -DF_$* $< -c -o $@
+
+$(FDMAN_OBJS): fdman.c
+ $(COMPILE) -DF_$* $< -c -o $@
+
+$(SELECT_OBJS): select.c
+ $(COMPILE) -DF_$* $< -c -o $@
+
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
Index: libc/sys/psp/select.c
===================================================================
--- libc/sys/psp/select.c (revision 0)
+++ libc/sys/psp/select.c (revision 0)
@@ -0,0 +1,172 @@
+/*
+ * PSP Software Development Kit - http://www.pspdev.org
+ * -----------------------------------------------------------------------
+ * Licensed under the BSD license, see LICENSE in PSPSDK root for details.
+ *
+ * pipe.c - Socket wrappers to provide similar functions to normal unix
+ *
+ * Copyright (c) 2006 Rafael Cabezas <rafpsp@gmail.com>
+ *
+ */
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/select.h>
+#include <psptypes.h>
+#include <pspthreadman.h>
+
+#include "fdman.h"
+
+#define SELECT_POLLING_DELAY_IN_us 100
+
+static int __psp_poll_select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds);
+
+int select(int n, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, struct timeval *timeout)
+{
+ int count;
+ clock_t start_time, time;
+
+ start_time = clock();
+
+ count = 0;
+
+ if (timeout) {
+ time = (timeout->tv_sec * CLOCKS_PER_SEC) + (timeout->tv_usec * (1*1000*1000/CLOCKS_PER_SEC));
+ }
+ else {
+ time = 0;
+ }
+
+ for (;;) {
+ count = __psp_poll_select(n, readfds, writefds, exceptfds);
+ /* If timeout == NULL, then don't timeout! */
+ if ( (count > 0) || ((timeout != NULL) && ((clock() - start_time) >= time)) ) {
+ break;
+ }
+ else {
+ /* Nothing found, and not timed-out yet; let's yield for SELECT_POLLING_DELAY_IN_us, so we're not in a busy loop */
+ sceKernelDelayThread(SELECT_POLLING_DELAY_IN_us);
+ }
+ }
+
+ return count;
+}
+
+#define SCE_FD_SET(n, p) \
+ ((p)->fds_bits[((n) & 0xFF) /__NFDBITS] |= (1 << ((n) % __NFDBITS)))
+
+static int __psp_poll_select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
+{
+ int fd, count;
+ fd_set ready_readfds, ready_writefds, ready_exceptfds;
+ fd_set scereadfds, scewritefds, sceexceptfds;
+ SceKernelMppInfo info;
+ struct timeval scetv;
+
+ FD_ZERO(&ready_readfds);
+ FD_ZERO(&ready_writefds);
+ FD_ZERO(&ready_exceptfds);
+
+ info.size = sizeof(info);
+ scetv.tv_sec = 0;
+ scetv.tv_usec = 0;
+ count = 0;
+
+ for (fd = 0; fd < n; fd++)
+ {
+ if (__psp_descriptormap[fd] != NULL) {
+ switch(__psp_descriptormap[fd]->type)
+ {
+ case __PSP_DESCRIPTOR_TYPE_PIPE:
+ if (readfds && FD_ISSET(fd, readfds)) {
+ if (sceKernelReferMsgPipeStatus(__psp_descriptormap[fd]->sce_descriptor, &info) == 0) {
+ if (info.bufSize != info.freeSize) {
+ FD_SET(fd, &ready_readfds);
+ count++;
+ }
+ }
+ else {
+ FD_SET(fd, &ready_exceptfds);
+ count++;
+ }
+ }
+ if (writefds && FD_ISSET(fd, writefds)) {
+ if (sceKernelReferMsgPipeStatus(__psp_descriptormap[fd]->sce_descriptor, &info) == 0) {
+ if (info.freeSize > 0) {
+ FD_SET(fd, &ready_writefds);
+ count++;
+ }
+ }
+ else {
+ FD_SET(fd, &ready_exceptfds);
+ count++;
+ }
+ }
+ break;
+ case __PSP_DESCRIPTOR_TYPE_FILE:
+ if (readfds && FD_ISSET(fd, readfds)) {
+ if (readfds && FD_ISSET(fd, readfds)) {
+ /** Just set it for now */
+ FD_SET(fd, &ready_readfds);
+ count++;
+ }
+ }
+ break;
+ case __PSP_DESCRIPTOR_TYPE_SOCKET:
+ if (readfds && FD_ISSET(fd, readfds)) {
+ int sce_ret, sce_fd;
+ sce_fd = __psp_descriptormap[fd]->sce_descriptor;
+ FD_ZERO(&scereadfds);
+ SCE_FD_SET(sce_fd, &scereadfds);
+ errno = 0;
+ sce_ret = sceNetInetSelect (sce_fd+1, &scereadfds, NULL, NULL, &scetv);
+ if (sce_ret>0) {
+ FD_SET(fd, &ready_readfds);
+ count++;
+ }
+ else if (sce_ret == -1) {
+ errno = sceNetInetGetErrno();
+ if (exceptfds && FD_ISSET(fd, exceptfds)) {
+ FD_SET(fd, &ready_exceptfds);
+ count++;
+ } else {
+ count = -1;
+ }
+ }
+ }
+ if (writefds && FD_ISSET(fd, writefds)) {
+ int sce_ret;
+ FD_ZERO(&scewritefds);
+ SCE_FD_SET(__psp_descriptormap[fd]->sce_descriptor, &scewritefds);
+ sce_ret = sceNetInetSelect (__psp_descriptormap[fd]->sce_descriptor+1, NULL, &scewritefds, NULL, &scetv);
+ if (sce_ret>0) {
+ FD_SET(fd, &ready_writefds);
+ count++;
+ }
+ else if (sce_ret == -1) {
+ if (exceptfds && FD_ISSET(fd, exceptfds)) {
+ FD_SET(fd, &ready_exceptfds);
+ count++;
+ }
+ else {
+ count = -1;
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ if (count > 0) {
+ if (readfds)
+ *readfds = ready_readfds;
+ if (writefds)
+ *writefds = ready_writefds;
+ if (exceptfds)
+ *exceptfds = ready_exceptfds;
+ }
+
+ return count;
+}
+
Property changes on: libc/sys/psp/select.c
___________________________________________________________________
Name: svn:eol-style
+ native
Index: libc/sys/psp/fdman.c
===================================================================
--- libc/sys/psp/fdman.c (revision 0)
+++ libc/sys/psp/fdman.c (revision 0)
@@ -0,0 +1,103 @@
+/*
+ * PSP Software Development Kit - http://www.pspdev.org
+ * -----------------------------------------------------------------------
+ * Licensed under the BSD license, see LICENSE in PSPSDK root for details.
+ *
+ * fdman.c - File descriptor management.
+ *
+ * Copyright (c) 2006 Rafael Cabezas <rafpsp@gmail.com>
+ */
+
+#include <psptypes.h>
+#include <errno.h>
+#include "fdman.h"
+
+static __psp_descriptormap_type __psp_descriptor_data_pool[__PSP_FILENO_MAX];
+__psp_descriptormap_type *__psp_descriptormap [__PSP_FILENO_MAX];
+
+void __psp_fdman_init()
+{
+ int scefd;
+
+ /* Initialize descriptor data*/
+ memset(__psp_descriptor_data_pool, 0, sizeof(__psp_descriptormap_type) *__PSP_FILENO_MAX);
+ /* Initialize descriptor map*/
+ memset(__psp_descriptormap, 0, sizeof(__psp_descriptormap_type*)*__PSP_FILENO_MAX);
+
+ scefd = sceKernelStdin();
+ if ((scefd >= 0) && (scefd < __PSP_FILENO_MAX)) {
+ __psp_descriptormap[0] = &__psp_descriptor_data_pool[0];
+ __psp_descriptormap[0]->sce_descriptor = scefd;
+ __psp_descriptormap[0]->type = __PSP_DESCRIPTOR_TYPE_TTY;
+ }
+ scefd = sceKernelStdout();
+ if ((scefd >= 0) && (scefd < __PSP_FILENO_MAX)) {
+ __psp_descriptormap[1] = &__psp_descriptor_data_pool[1];
+ __psp_descriptormap[1]->sce_descriptor = scefd;
+ __psp_descriptormap[1]->type = __PSP_DESCRIPTOR_TYPE_TTY;
+ }
+ scefd = sceKernelStderr();
+ if ((scefd >= 0) && (scefd < __PSP_FILENO_MAX)) {
+ __psp_descriptormap[2] = &__psp_descriptor_data_pool[2];
+ __psp_descriptormap[2]->sce_descriptor = scefd;
+ __psp_descriptormap[2]->type = __PSP_DESCRIPTOR_TYPE_TTY;
+ }
+}
+
+int __psp_fdman_get_new_descriptor()
+{
+ int i = 0;
+//lock here
+ for (i = 0; i < __PSP_FILENO_MAX; i++) {
+ if (__psp_descriptormap[i] == NULL) {
+ __psp_descriptormap[i] = &__psp_descriptor_data_pool[i];
+ __psp_descriptormap[i]->ref_count++;
+ return i;
+ }
+ }
+//unlock here
+
+ errno = ENOMEM;
+ return -1;
+}
+
+int __psp_fdman_get_dup_descriptor(int fd)
+{
+ int i = 0;
+
+ if (fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd] == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ //lock here
+ for (i = 0; i < __PSP_FILENO_MAX; i++) {
+ if (__psp_descriptormap[i] == NULL) {
+ __psp_descriptormap[i] = &__psp_descriptor_data_pool[fd];
+ __psp_descriptormap[i]->ref_count++;
+ return i;
+ }
+ }
+ //unlock here
+
+ errno = ENOMEM;
+ return -1;
+}
+
+void __psp_fdman_release_descriptor(int fd)
+{
+ __psp_descriptormap[fd]->ref_count--;
+
+ if (__psp_descriptormap[fd]->ref_count == 0) {
+
+ if (__psp_descriptormap[fd]->filename != NULL) {
+ free(__psp_descriptormap[fd]->filename);
+ }
+ __psp_descriptormap[fd]->filename = NULL;
+ __psp_descriptormap[fd]->sce_descriptor = 0;
+ __psp_descriptormap[fd]->type = 0;//__PSP_DESCRIPTOR_TYPE_NA;
+ __psp_descriptormap[fd]->flags = 0;
+
+ }
+ __psp_descriptormap[fd] = NULL;
+}
Property changes on: libc/sys/psp/fdman.c
___________________________________________________________________
Name: svn:eol-style
+ native
Index: libc/sys/psp/libcglue.c
===================================================================
--- libc/sys/psp/libcglue.c (revision 1866)
+++ libc/sys/psp/libcglue.c (working copy)
@@ -35,6 +35,7 @@
#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);
@@ -47,8 +48,12 @@
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));
-#define __PSP_FILENO_MAX 1024
-extern char * __psp_filename_map[__PSP_FILENO_MAX];
+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);
@@ -158,7 +163,7 @@
#ifdef F__open
int _open(const char *name, int flags, int mode)
{
- int fd;
+ int scefd, fd;
int sce_flags;
char dest[MAXPATHLEN + 1];
@@ -188,79 +193,166 @@
sce_flags |= PSP_O_NBLOCK;
}
- fd = sceIoOpen(dest, sce_flags, mode);
- if ((fd >= 0) && (fd < __PSP_FILENO_MAX)) {
- __psp_filename_map[fd] = strdup(dest);
+ 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);
}
- return __psp_set_errno(fd);
+
}
#endif
#ifdef F__close
int _close(int fd)
{
- if (fd < 0) {
+ int ret = 0;
+
+ if (fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd] == NULL) {
errno = EBADF;
return -1;
}
- if (SOCKET_IS_VALID(fd) && __psp_socket_close != NULL) {
- return __psp_socket_close(fd);
+ 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;
}
- if ((fd >= 0) && (fd < __PSP_FILENO_MAX)) {
- if (__psp_filename_map[fd] != NULL) {
- free(__psp_filename_map[fd]);
- __psp_filename_map[fd] = NULL;
- }
- }
-
- return __psp_set_errno(sceIoClose(fd));
+ errno = EBADF;
+ return -1;
}
#endif
#ifdef F__read
int _read(int fd, void *buf, size_t size)
{
- if (fd < 0) {
+ if (fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd] == NULL) {
errno = EBADF;
return -1;
}
- if (SOCKET_IS_VALID(fd) && __psp_socket_recv != NULL) {
- return __psp_socket_recv(fd, buf, size, 0);
+ 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;
}
- return __psp_set_errno(sceIoRead(fd, buf, size));
+ errno = EBADF;
+ return -1;
+
}
#endif
#ifdef F__write
int _write(int fd, const void *buf, size_t size)
{
- if (fd < 0) {
+ if (fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd] == NULL) {
errno = EBADF;
return -1;
}
- if (SOCKET_IS_VALID(fd) && __psp_socket_send != NULL) {
- return __psp_socket_send(fd, buf, size, 0);
+ 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;
}
- return __psp_set_errno(sceIoWrite(fd, buf, size));
+ errno = EBADF;
+ return -1;
}
#endif
#ifdef F__lseek
off_t _lseek(int fd, off_t offset, int whence)
{
- if (fd < 0) {
+ if (fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd] == NULL) {
errno = EBADF;
return -1;
}
- /* We don't have to do anything with the whence argument because SEEK_* == PSP_SEEK_*. */
- return (off_t) __psp_set_errno(sceIoLseek(fd, offset, whence));
+ 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
@@ -466,26 +558,37 @@
{
int ret;
SceOff oldpos;
- if ((fd >= 0) && (fd < __PSP_FILENO_MAX)) {
- if (__psp_filename_map[fd] != NULL) {
- if (strcmp(__psp_filename_map[fd], " __PSP_STDIO") == 0) {
- memset(sbuf, '\0', sizeof(struct stat));
- sbuf->st_mode = S_IFCHR;
- return 0;
- } else {
- ret = stat(__psp_filename_map[fd], sbuf);
+ if (fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd] == NULL) {
+ 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(fd, 0, SEEK_CUR);
+ oldpos = sceIoLseek(__psp_descriptormap[fd]->sce_descriptor, 0, SEEK_CUR);
if (oldpos != (off_t) -1) {
- sbuf->st_size = (off_t) sceIoLseek(fd, 0, SEEK_END);
- sceIoLseek(fd, oldpos, SEEK_SET);
+ 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;
}
@@ -494,16 +597,17 @@
#ifdef F_isatty
int isatty(int fd)
{
- if ((fd >= 0) && (fd < __PSP_FILENO_MAX)) {
- if (__psp_filename_map[fd] != NULL) {
- if (strcmp(__psp_filename_map[fd], " __PSP_STDIO") == 0) {
- return 1;
- } else {
- return 0;
- }
- }
+ if (fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd] == NULL) {
+ errno = EBADF;
+ return 0;
}
- return 0;
+
+ if (__psp_descriptormap[fd]->type == __PSP_DESCRIPTOR_TYPE_TTY) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
}
#endif
@@ -627,6 +731,68 @@
}
#endif
+#ifdef F__fcntl
+int _fcntl(int fd, int cmd, ...)
+{
+ if (fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd] == NULL) {
+ 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)
{
@@ -717,27 +883,13 @@
*/
void __psp_libc_init(int argc, char *argv[])
{
- int fd;
(void) argc;
/* Initialize cwd from this program's path */
__psp_init_cwd(argv[0]);
- /* Initialize filenamap */
- memset(__psp_filename_map, '\0', sizeof(char *) * __PSP_FILENO_MAX);
-
- fd = sceKernelStdin();
- if ((fd >= 0) && (fd < __PSP_FILENO_MAX)) {
- __psp_filename_map[fd] = strdup(" __PSP_STDIO");
- }
- fd = sceKernelStdout();
- if ((fd >= 0) && (fd < __PSP_FILENO_MAX)) {
- __psp_filename_map[fd] = strdup(" __PSP_STDIO");
- }
- fd = sceKernelStderr();
- if ((fd >= 0) && (fd < __PSP_FILENO_MAX)) {
- __psp_filename_map[fd] = strdup(" __PSP_STDIO");
- }
+ /* Initialize filedescriptor management */
+ __psp_fdman_init();
}
#endif /* F__exit */
Index: libc/sys/psp/socket.c
===================================================================
--- libc/sys/psp/socket.c (revision 1866)
+++ libc/sys/psp/socket.c (working copy)
@@ -9,6 +9,7 @@
* Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
*
*/
+#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/select.h>
@@ -16,57 +17,48 @@
#include <arpa/inet.h>
#include <psptypes.h>
+#include "fdman.h"
-#define __PSP_SOCKET_MAX 1024
-extern char __psp_socket_map[__PSP_SOCKET_MAX];
-
-#ifdef F___psp_socket_map
-char __psp_socket_map[__PSP_SOCKET_MAX];
-#endif
-
#ifdef F_socket
int socket(int domain, int type, int protocol)
{
- int sock;
+ int sock, scesock;
int i;
- sock = sceNetInetSocket(domain, type, protocol);
- if(sock < 0)
- {
+ scesock = sceNetInetSocket(domain, type, protocol);
+ if(scesock < 0) {
errno = sceNetInetGetErrno();
return -1;
}
- if((sock >= 0) && (sock < __PSP_SOCKET_MAX))
- {
- __psp_socket_map[sock] = 1;
+ sock = __psp_fdman_get_new_descriptor();
+ if( sock != -1 ) {
+ __psp_descriptormap[sock]->sce_descriptor = scesock;
+ __psp_descriptormap[sock]->type = __PSP_DESCRIPTOR_TYPE_SOCKET;
}
- else
- {
- sceNetInetClose(sock);
+ else {
+ sceNetInetClose(scesock);
errno = ENOENT;
return -1;
}
- return sock | SOCKET_FD_PAT;
+ return sock;
}
/* These are glue routines that are called from _close(), _read(), and
_write(). They are here so that any program that uses socket() will pull
them in and have expanded socket capability. */
-int __psp_socket_close(int s)
+int __psp_socket_close(int sock)
{
- int ret;
- int sock;
+ int ret = 0;
- sock = SOCKET_GET_SOCK(s);
- if((sock > 0) && (sock < __PSP_SOCKET_MAX))
- {
- __psp_socket_map[sock] = 0;
+ if (__psp_descriptormap[sock]->ref_count == 1) {
+ ret = sceNetInetClose(__psp_descriptormap[sock]->sce_descriptor);
}
- ret = sceNetInetClose(sock);
+ __psp_fdman_release_descriptor(sock);
+
if(ret < 0)
{
/* If close is defined likely errno is */
@@ -91,36 +83,32 @@
#ifdef F_accept
int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
{
- int sock;
- int new;
+ int newscesock, newsock;
- if(!(SOCKET_IS_VALID(s)))
- {
+ if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET) {
errno = EBADF;
return -1;
}
- sock = SOCKET_GET_SOCK(s);
-
- if(__psp_socket_map[sock] == 0)
- {
- errno = EBADF;
- return -1;
+ newscesock = sceNetInetAccept(__psp_descriptormap[s]->sce_descriptor, addr, addrlen);
+ if( (newscesock >= 0) ) {
+ newsock = __psp_fdman_get_new_descriptor();
+ if ( newsock != -1 ) {
+ __psp_descriptormap[newsock]->sce_descriptor = newscesock;
+ __psp_descriptormap[newsock]->type = __PSP_DESCRIPTOR_TYPE_SOCKET;
+ }
+ else {
+ sceNetInetClose(newscesock);
+ errno = ENOENT;
+ return -1;
+ }
}
-
- new = sceNetInetAccept(sock, addr, addrlen);
- if((new >= 0) && (new < __PSP_SOCKET_MAX))
- {
- __psp_socket_map[new] = 1;
- }
- else
- {
- sceNetInetClose(new);
+ else {
errno = ENOENT;
return -1;
}
- return new | SOCKET_FD_PAT;
+ return newsock;
}
#endif
@@ -128,23 +116,14 @@
int bind(int s, const struct sockaddr *my_addr, socklen_t addrlen)
{
int ret;
- int sock;
- if(!(SOCKET_IS_VALID(s)))
+ if( __psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET )
{
errno = EBADF;
return -1;
}
- sock = SOCKET_GET_SOCK(s);
-
- if(__psp_socket_map[sock] == 0)
- {
- errno = EBADF;
- return -1;
- }
-
- ret = sceNetInetBind(sock, my_addr, addrlen);
+ ret = sceNetInetBind(__psp_descriptormap[s]->sce_descriptor, my_addr, addrlen);
if(ret < 0)
{
errno = sceNetInetGetErrno();
@@ -158,30 +137,21 @@
#ifdef F_connect
int connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
{
- int sock;
int ret;
- if(!(SOCKET_IS_VALID(s)))
+ if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
{
errno = EBADF;
return -1;
}
- sock = SOCKET_GET_SOCK(s);
-
- if(__psp_socket_map[sock] == 0)
- {
- errno = EBADF;
- return -1;
- }
-
- ret = sceNetInetConnect(sock, serv_addr, addrlen);
+ ret = sceNetInetConnect(__psp_descriptormap[s]->sce_descriptor, serv_addr, addrlen);
if(ret < 0)
{
errno = sceNetInetGetErrno();
return -1;
}
-
+
return 0;
}
#endif
@@ -189,30 +159,21 @@
#ifdef F_setsockopt
int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
{
- int sock;
int ret;
- if(!(SOCKET_IS_VALID(s)))
+ if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
{
errno = EBADF;
return -1;
}
- sock = SOCKET_GET_SOCK(s);
-
- if(__psp_socket_map[sock] == 0)
- {
- errno = EBADF;
- return -1;
- }
-
- ret = sceNetInetGetsockopt(sock, level, optname, optval, optlen);
+ ret = sceNetInetGetsockopt(__psp_descriptormap[s]->sce_descriptor, level, optname, optval, optlen);
if(ret < 0)
{
errno = sceNetInetGetErrno();
return -1;
}
-
+
return 0;
}
#endif
@@ -220,24 +181,15 @@
#ifdef F_listen
int listen(int s, int backlog)
{
- int sock;
int ret;
- if(!(SOCKET_IS_VALID(s)))
+ if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
{
errno = EBADF;
return -1;
}
- sock = SOCKET_GET_SOCK(s);
-
- if(__psp_socket_map[sock] == 0)
- {
- errno = EBADF;
- return -1;
- }
-
- ret = sceNetInetListen(sock, backlog);
+ ret = sceNetInetListen(__psp_descriptormap[s]->sce_descriptor, backlog);
if(ret < 0)
{
errno = sceNetInetGetErrno();
@@ -251,24 +203,15 @@
#ifdef F_recv
ssize_t recv(int s, void *buf, size_t len, int flags)
{
- int sock;
int ret;
- if(!(SOCKET_IS_VALID(s)))
+ if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
{
errno = EBADF;
return -1;
}
- sock = SOCKET_GET_SOCK(s);
-
- if(__psp_socket_map[sock] == 0)
- {
- errno = EBADF;
- return -1;
- }
-
- ret = sceNetInetRecv(sock, buf, len, flags);
+ ret = sceNetInetRecv(__psp_descriptormap[s]->sce_descriptor, buf, len, flags);
if(ret < 0)
{
errno = sceNetInetGetErrno();
@@ -282,24 +225,15 @@
#ifdef F_recvfrom
ssize_t recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
{
- int sock;
int ret;
- if(!(SOCKET_IS_VALID(s)))
+ if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
{
errno = EBADF;
return -1;
}
- sock = SOCKET_GET_SOCK(s);
-
- if(__psp_socket_map[sock] == 0)
- {
- errno = EBADF;
- return -1;
- }
-
- ret = sceNetInetRecvfrom(sock, buf, len, flags, from, fromlen);
+ ret = sceNetInetRecvfrom(__psp_descriptormap[s]->sce_descriptor, buf, len, flags, from, fromlen);
if(ret < 0)
{
errno = sceNetInetGetErrno();
@@ -313,24 +247,15 @@
#ifdef F_send
ssize_t send(int s, const void *buf, size_t len, int flags)
{
- int sock;
int ret;
- if(!(SOCKET_IS_VALID(s)))
+ if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
{
errno = EBADF;
return -1;
}
- sock = SOCKET_GET_SOCK(s);
-
- if(__psp_socket_map[sock] == 0)
- {
- errno = EBADF;
- return -1;
- }
-
- ret = sceNetInetSend(sock, buf, len, flags);
+ ret = sceNetInetSend(__psp_descriptormap[s]->sce_descriptor, buf, len, flags);
if(ret < 0)
{
errno = sceNetInetGetErrno();
@@ -344,24 +269,15 @@
#ifdef F_sendto
ssize_t sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
{
- int sock;
int ret;
- if(!(SOCKET_IS_VALID(s)))
+ if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
{
errno = EBADF;
return -1;
}
- sock = SOCKET_GET_SOCK(s);
-
- if(__psp_socket_map[sock] == 0)
- {
- errno = EBADF;
- return -1;
- }
-
- ret = sceNetInetSendto(sock, buf, len, flags, to, tolen);
+ ret = sceNetInetSendto(__psp_descriptormap[s]->sce_descriptor, buf, len, flags, to, tolen);
if(ret < 0)
{
errno = sceNetInetGetErrno();
@@ -375,29 +291,31 @@
#ifdef F_setsockopt
int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
{
- int sock;
int ret;
- if(!(SOCKET_IS_VALID(s)))
+ if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
{
errno = EBADF;
return -1;
}
- sock = SOCKET_GET_SOCK(s);
-
- if(__psp_socket_map[sock] == 0)
- {
- errno = EBADF;
- return -1;
- }
-
- ret = sceNetInetSetsockopt(sock, level, optname, optval, optlen);
+ ret = sceNetInetSetsockopt(__psp_descriptormap[s]->sce_descriptor, level, optname, optval, optlen);
if(ret < 0)
{
errno = sceNetInetGetErrno();
return -1;
}
+ else
+ {
+ if ( (level == SOL_SOCKET) && (optname == SO_NONBLOCK) ) {
+ if (*((int*)optval) == 1) {
+ __psp_descriptormap[s]->flags |= O_NONBLOCK;
+ }
+ else {
+ __psp_descriptormap[s]->flags &= ~O_NONBLOCK;
+ }
+ }
+ }
return 0;
}
@@ -406,24 +324,15 @@
#ifdef F_shutdown
int shutdown(int s, int how)
{
- int sock;
int ret;
- if(!(SOCKET_IS_VALID(s)))
+ if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
{
errno = EBADF;
return -1;
}
- sock = SOCKET_GET_SOCK(s);
-
- if(__psp_socket_map[sock] == 0)
- {
- errno = EBADF;
- return -1;
- }
-
- ret = sceNetInetShutdown(sock, how);
+ ret = sceNetInetShutdown(__psp_descriptormap[s]->sce_descriptor, how);
if(ret < 0)
{
errno = sceNetInetGetErrno();
@@ -437,24 +346,15 @@
#ifdef F_getpeername
int getpeername(int s, struct sockaddr *name, socklen_t *namelen)
{
- int sock;
int ret;
- if(!(SOCKET_IS_VALID(s)))
+ if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
{
errno = EBADF;
return -1;
}
- sock = SOCKET_GET_SOCK(s);
-
- if(__psp_socket_map[sock] == 0)
- {
- errno = EBADF;
- return -1;
- }
-
- ret = sceNetInetGetpeername(sock, name, namelen);
+ ret = sceNetInetGetpeername(__psp_descriptormap[s]->sce_descriptor, name, namelen);
if(ret < 0)
{
errno = sceNetInetGetErrno();
@@ -468,24 +368,15 @@
#ifdef F_getsockname
int getsockname(int s, struct sockaddr *name, socklen_t *namelen)
{
- int sock;
int ret;
- if(!(SOCKET_IS_VALID(s)))
+ if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
{
errno = EBADF;
return -1;
}
- sock = SOCKET_GET_SOCK(s);
-
- if(__psp_socket_map[sock] == 0)
- {
- errno = EBADF;
- return -1;
- }
-
- ret = sceNetInetGetsockname(sock, name, namelen);
+ ret = sceNetInetGetsockname(__psp_descriptormap[s]->sce_descriptor, name, namelen);
if(ret < 0)
{
errno = sceNetInetGetErrno();
@@ -496,23 +387,6 @@
}
#endif
-#ifdef F_select
-int select(int n, fd_set *readfds, fd_set *writefds,
- fd_set *exceptfds, struct timeval *timeout)
-{
- int ret;
-
- ret = sceNetInetSelect(n, readfds, writefds, exceptfds, timeout);
- if(ret < 0)
- {
- errno = sceNetInetGetErrno();
- return -1;
- }
-
- return ret;
-}
-#endif
-
#ifdef F_inet_ntoa
char *inet_ntoa(struct in_addr in)
{
Index: libc/sys/psp/Makefile.am
===================================================================
--- libc/sys/psp/Makefile.am (revision 1866)
+++ libc/sys/psp/Makefile.am (working copy)
@@ -12,19 +12,26 @@
_link.o _unlink.o sleep.o opendir.o readdir.o \
closedir.o getcwd.o chdir.o mkdir.o rmdir.o \
realpath.o _stat.o truncate.o access.o tzset.o \
- __psp_set_errno.o mlock.o
+ __psp_set_errno.o mlock.o _fcntl.o
SOCKET_MULT_OBJS = socket.o accept.o bind.o connect.o getsockopt.o \
listen.o recv.o recvfrom.o send.o sendto.o \
- setsockopt.o shutdown.o __psp_socket_map.o \
- getsockname.o getpeername.o select.o inet_ntoa.o
+ setsockopt.o shutdown.o getsockname.o getpeername.o \
+ inet_ntoa.o
+
+PIPE_OBJS = pipe.o
+FDMAN_OBJS = fdman.o
+
+SELECT_OBJS = select.o
+
XPRINTF_MULT_OBJS = vxprintf.o _xprintf.o __sout.o vsnprintf.o snprintf.o vsprintf.o sprintf.o __mout.o mprintf.o vmprintf.o asprintf.o vasprintf.o __fout.o fprintf.o vfprintf.o printf.o vprintf.o _sprintf_r.o
NETDB_MULT_OBJS = h_errno.o gethostbyaddr.o gethostbyname.o
-lib_a_SOURCES = libcglue.c socket.c pspcwd.c xprintf.c netdb.c
-lib_a_LIBADD = $(LIBCGLUE_MULT_OBJS) $(SOCKET_MULT_OBJS) $(XPRINTF_MULT_OBJS) $(NETDB_MULT_OBJS)
+lib_a_SOURCES = libcglue.c socket.c pspcwd.c xprintf.c netdb.c pipe.c fdman.c select.c
+lib_a_LIBADD = $(LIBCGLUE_MULT_OBJS) $(SOCKET_MULT_OBJS) $(XPRINTF_MULT_OBJS) \
+ $(NETDB_MULT_OBJS) $(PIPE_OBJS) $(FDMAN_OBJS) $(SELECT_OBJS)
all: crt0.o
@@ -40,5 +47,14 @@
$(NETDB_MULT_OBJS): netdb.c
$(COMPILE) -DF_$* $< -c -o $@
+$(PIPE_OBJS): pipe.c
+ $(COMPILE) -DF_$* $< -c -o $@
+
+$(FDMAN_OBJS): fdman.c
+ $(COMPILE) -DF_$* $< -c -o $@
+
+$(SELECT_OBJS): select.c
+ $(COMPILE) -DF_$* $< -c -o $@
+
ACLOCAL_AMFLAGS = -I ../../..
CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host
Index: libc/sys/psp/fdman.h
===================================================================
--- libc/sys/psp/fdman.h (revision 0)
+++ libc/sys/psp/fdman.h (revision 0)
@@ -0,0 +1,38 @@
+/*
+ * PSP Software Development Kit - http://www.pspdev.org
+ * -----------------------------------------------------------------------
+ * Licensed under the BSD license, see LICENSE in PSPSDK root for details.
+ *
+ * fdman.h - File descriptor management.
+ *
+ * Copyright (c) 2006 Rafael Cabezas <rafpsp@gmail.com>
+ */
+
+#ifndef _FDMAN_H_
+ #define _FDMAN_H_
+
+ #define __PSP_FILENO_MAX 1024
+
+ typedef enum {
+ __PSP_DESCRIPTOR_TYPE_FILE ,
+ __PSP_DESCRIPTOR_TYPE_PIPE ,
+ __PSP_DESCRIPTOR_TYPE_SOCKET,
+ __PSP_DESCRIPTOR_TYPE_TTY
+ } __psp_fdman_fd_types;
+
+ typedef struct {
+ char * filename;
+ u8 type;
+ u32 sce_descriptor;
+ u32 flags;
+ u32 ref_count;
+ } __psp_descriptormap_type;
+
+ extern __psp_descriptormap_type *__psp_descriptormap[__PSP_FILENO_MAX];
+
+ void __psp_fdman_init();
+ int __psp_fdman_get_new_descriptor();
+ int __psp_fdman_get_dup_descriptor(int fd);
+ void __psp_fdman_release_descriptor(int fd);
+
+#endif
Property changes on: libc/sys/psp/fdman.h
___________________________________________________________________
Name: svn:eol-style
+ native
Index: libc/sys/psp/sys/fd_set.h
===================================================================
--- libc/sys/psp/sys/fd_set.h (revision 1866)
+++ libc/sys/psp/sys/fd_set.h (working copy)
@@ -56,11 +56,14 @@
} fd_set;
#define FD_SET(n, p) \
- ((p)->fds_bits[((n) & 0xFF) /__NFDBITS] |= (1 << ((n) % __NFDBITS)))
+ ((p)->fds_bits[(n) /__NFDBITS] |= (1 << ((n) % __NFDBITS)))
+
#define FD_CLR(n, p) \
- ((p)->fds_bits[((n) & 0xFF) /__NFDBITS] &= ~(1 << ((n) % __NFDBITS)))
+ ((p)->fds_bits[(n) /__NFDBITS] &= ~(1 << ((n) % __NFDBITS)))
+
#define FD_ISSET(n, p) \
- ((p)->fds_bits[((n) & 0xFF) /__NFDBITS] & (1 << ((n) % __NFDBITS)))
+ ((p)->fds_bits[(n) /__NFDBITS] & (1 << ((n) % __NFDBITS)))
+
#define FD_ZERO(p) (void)__builtin_memset((p), 0, sizeof(*(p)))
#endif /* _SYS_FD_SET_H_ */
Index: libc/sys/psp/sys/socket.h
===================================================================
--- libc/sys/psp/sys/socket.h (revision 1866)
+++ libc/sys/psp/sys/socket.h (working copy)
@@ -110,6 +110,7 @@
#define SO_ERROR 0x1007 /* get error status and clear */
#define SO_TYPE 0x1008 /* get socket type */
#define SO_OVERFLOWED 0x1009 /* datagrams: return packets dropped */
+#define SO_NONBLOCK 0x1009 /* non-blocking I/O */
/*
* Structure used for manipulating linger option.
@@ -266,10 +267,6 @@
int shutdown(int, int);
int socket(int, int, int);
-#define SOCKET_FD_PAT 0x7F000000
-#define SOCKET_IS_VALID(x) (((x) & SOCKET_FD_PAT) == SOCKET_FD_PAT)
-#define SOCKET_GET_SOCK(x) ((x) & ~SOCKET_FD_PAT)
-
/* sceNetInet socket API. */
int sceNetInetAccept(int s, struct sockaddr *addr, socklen_t *addrlen);
int sceNetInetBind(int s, const struct sockaddr *my_addr, socklen_t addrlen);
Index: libc/sys/psp/pipe.c
===================================================================
--- libc/sys/psp/pipe.c (revision 0)
+++ libc/sys/psp/pipe.c (revision 0)
@@ -0,0 +1,265 @@
+/*
+ * PSP Software Development Kit - http://www.pspdev.org
+ * -----------------------------------------------------------------------
+ * Licensed under the BSD license, see LICENSE in PSPSDK root for details.
+ *
+ * pipe.c - Socket wrappers to provide similar functions to normal unix
+ *
+ * Copyright (c) 2006 Rafael Cabezas <rafpsp@gmail.com>
+ *
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <sys/syslimits.h>
+#include <sys/fd_set.h>
+
+#include <psptypes.h>
+#include <pspthreadman.h>
+#include <pspmodulemgr.h>
+#include <pspkerror.h>
+#include "fdman.h"
+
+/* Pipe functions */
+/* Returns how many bytes are in the pipe -- waiting to be read */
+size_t __psp_pipe_peekmsgsize(int fd)
+{
+ SceKernelMppInfo info;
+ info.size = sizeof(info);
+ if (sceKernelReferMsgPipeStatus(__psp_descriptormap[fd]->sce_descriptor, &info) == 0) {
+ return (info.bufSize - info.freeSize);
+ }
+ else {
+ return -1;
+ }
+}
+
+int pipe(int fildes[2])
+{
+ static int iIndex = 0;
+ char name[32];
+ iIndex++;
+
+ sprintf(name, "__psp_pipe_%02d", iIndex);
+
+ SceUID uid = sceKernelCreateMsgPipe(name, PSP_MEMORY_PARTITION_USER, 0, (void *)PIPE_BUF, NULL);
+
+ if (uid >= 0) {
+ fildes[0] = __psp_fdman_get_new_descriptor();
+ if (fildes[0] != -1) {
+ __psp_descriptormap[fildes[0]]->sce_descriptor = uid;
+ __psp_descriptormap[fildes[0]]->type = __PSP_DESCRIPTOR_TYPE_PIPE;
+ }
+ else {
+ sceKernelDeleteMsgPipe(uid);
+ errno = EFAULT;
+ return -1;
+ }
+
+ fildes[1] = __psp_fdman_get_dup_descriptor(fildes[0]);
+ if (fildes[1] != -1) {
+ __psp_descriptormap[fildes[1]]->sce_descriptor = uid;
+ return 0;
+ }
+ else {
+ sceKernelDeleteMsgPipe(uid);
+ errno = EFAULT;
+ return -1;
+ }
+
+ }
+ else {
+ errno = EFAULT;
+ return -1;
+ }
+}
+
+int __psp_pipe_close(int fd)
+{
+ int ret = 0;
+
+ if( fd < 0 || fd > (__PSP_FILENO_MAX - 1) || (__psp_descriptormap[fd]->type != __PSP_DESCRIPTOR_TYPE_PIPE) ) {
+ errno = EBADF;
+ return -1;
+ }
+
+
+ if ( __psp_descriptormap[fd]->ref_count == 1 ) {
+ /**
+ * Delete a message pipe
+ *
+ * @param uid - The UID of the pipe
+ *
+ * @return 0 on success, < 0 on error
+ */
+ ret = sceKernelDeleteMsgPipe(__psp_descriptormap[fd]->sce_descriptor);
+ }
+
+ __psp_fdman_release_descriptor(fd);
+
+ if(ret < 0) {
+ return __psp_set_errno(ret);
+ }
+
+ return 0;
+}
+
+int __psp_pipe_nonblocking_read(int fd, void *buf, size_t len)
+{
+ int ret;
+ int sceuid;
+ int size;
+
+ if( fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd]->type != __PSP_DESCRIPTOR_TYPE_PIPE ) {
+ errno = EBADF;
+ return -1;
+ }
+
+ sceuid = __psp_descriptormap[fd]->sce_descriptor;
+
+ size = __psp_pipe_peekmsgsize(fd);
+ if (size > 0) {
+ if (size < len) {
+ len = size;
+ }
+ }
+ else {
+ errno = EBADF;
+ return -1;
+ }
+
+ /**
+ * Receive a message from a pipe
+ *
+ * @param uid - The UID of the pipe
+ * @param message - Pointer to the message
+ * @param size - Size of the message
+ * @param unk1 - Unknown
+ * @param unk2 - Unknown
+ * @param timeout - Timeout for receive
+ *
+ * @return 0 on success, < 0 on error
+ */
+ ret = sceKernelTryReceiveMsgPipe(sceuid, buf, len, 0, 0);
+
+ if (ret == 0) {/* Success - Data */
+ return len;
+ }
+ else if (ret == SCE_KERNEL_ERROR_MPP_EMPTY) {/* No data */
+ errno = EAGAIN;
+ return -1;
+ }
+ else {/* Error */
+ return __psp_set_errno(ret);
+ }
+}
+
+int __psp_pipe_read(int fd, void *buf, size_t len)
+{
+ int ret;
+ int sceuid;
+ int size;
+
+ if( fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd]->type != __PSP_DESCRIPTOR_TYPE_PIPE ) {
+ errno = EBADF;
+ return -1;
+ }
+
+ sceuid = __psp_descriptormap[fd]->sce_descriptor;
+
+ size = __psp_pipe_peekmsgsize(fd);
+ if (size > 0) {
+ if (size < len) {
+ len = size;
+ }
+ }
+ else {
+ errno = EBADF;
+ return -1;
+ }
+
+ /**
+ * Receive a message from a pipe
+ *
+ * @param uid - The UID of the pipe
+ * @param message - Pointer to the message
+ * @param size - Size of the message
+ * @param unk1 - Unknown
+ * @param unk2 - Unknown
+ * @param timeout - Timeout for receive
+ *
+ * @return 0 on success, < 0 on error
+ */
+ ret = sceKernelReceiveMsgPipe(sceuid, buf, len, 0, NULL, NULL);
+
+ if (ret == 0) {/* Success - Data */
+ return len;
+ }
+ else {/* Error */
+ return __psp_set_errno(ret);
+ }
+}
+
+int __psp_pipe_write(int fd, const void *buf, size_t len)
+{
+ int ret;
+ int sceuid;
+ char *cbuf;
+
+ if( fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd]->type != __PSP_DESCRIPTOR_TYPE_PIPE ) {
+ errno = EBADF;
+ return -1;
+ }
+
+ sceuid = __psp_descriptormap[fd]->sce_descriptor;
+
+ /**
+ * Send a message to a pipe
+ *
+ * @param uid - The UID of the pipe
+ * @param message - Pointer to the message
+ * @param size - Size of the message
+ * @param unk1 - Unknown
+ * @param unk2 - Unknown
+ * @param timeout - Timeout for send
+ *
+ * @return 0 on success, < 0 on error
+ */
+ cbuf = (char *)buf;
+ ret = sceKernelSendMsgPipe(sceuid, cbuf, len, 0, NULL, NULL);
+
+ if (ret == 0) {/* Success - Data */
+ return len;
+ }
+ else {/* Error */
+ return __psp_set_errno(ret);
+ }
+}
+
+int __psp_pipe_nonblocking_write(int fd, const void *buf, size_t len)
+{
+ int ret;
+ int sceuid;
+ char *cbuf;
+
+ if( fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd]->type != __PSP_DESCRIPTOR_TYPE_PIPE ) {
+ errno = EBADF;
+ return -1;
+ }
+
+ sceuid = __psp_descriptormap[fd]->sce_descriptor;
+
+ cbuf = (char *)buf;
+ ret = sceKernelTrySendMsgPipe(sceuid, cbuf, len, 0, 0);
+
+ if (ret == 0) {/* Success - Data */
+ return len;
+ }
+ else if (ret == SCE_KERNEL_ERROR_MPP_FULL) {
+ errno = EAGAIN;
+ return -1;
+ }
+ else {/* Error */
+ return __psp_set_errno(ret);
+ }
+}
+
Property changes on: libc/sys/psp/pipe.c
___________________________________________________________________
Name: svn:eol-style
+ native
Index: configure.host
===================================================================
--- configure.host (revision 1866)
+++ configure.host (working copy)
@@ -574,7 +574,7 @@
mipsallegrex*-psp-*)
sys_dir=psp
syscall_dir=syscalls
- newlib_cflags="${newlib_cflags} -G0 -DCOMPACT_CTYPE -DCLOCK_PROVIDED -DMALLOC_ALIGNMENT=16 -I${prefix}/psp/sdk/include" ;;
+ newlib_cflags="${newlib_cflags} -G0 -mno-explicit-relocs -DCOMPACT_CTYPE -DCLOCK_PROVIDED -DHAVE_FCNTL -DMALLOC_ALIGNMENT=16 -I${prefix}/psp/sdk/include" ;;
*)
newlib_cflags="${newlib_cflags} -DMISSING_SYSCALL_NAMES" ;;
esac
Raf.
PS: Edit: a bit of cleanup