newlib open(...) fix.

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
anhanguera
Posts: 31
Joined: Thu Aug 26, 2004 4:20 pm

newlib open(...) fix.

Post by anhanguera »

hi,

open(path, ...) fails if path has "//" ("path//file"), and here is the patch.

Code: Select all

--- libcglue.org.c      Wed Oct  5 13:24:55 2005
+++ libcglue.c  Wed Oct  5 14:03:27 2005
@@ -118,7 +118,14 @@
 int _open(const char *name, int flags, int mode)
 {
        int sce_flags;
+       char dest[MAXPATHLEN + 1];

+       /* Normalize pathname so that open("path//file") works */
+       if&#40;__psp_path_absolute&#40;name, dest, MAXPATHLEN&#41; < 0&#41; &#123;
+               errno = ENOENT;
+               return -1;
+       &#125;
+
        /* O_RDONLY starts at 0, where PSP_O_RDONLY starts at 1, so remap the read/write
           flags by adding 1. */
        sce_flags = &#40;flags & O_ACCMODE&#41; + 1;
@@ -140,7 +147,7 @@
                sce_flags |= PSP_O_NBLOCK;
        &#125;

-       return sceIoOpen&#40;name, sce_flags, mode&#41;;
+       return sceIoOpen&#40;dest, sce_flags, mode&#41;;
 &#125;
 #endif

alper "anhanguera" akcan
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

There are a bunch of cases like this that Sony doesn't handle in the "expected" way. I think I'll make all of the newlib stubs just normalize pathnames.
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

OK, done in rev 1121. The biggest remaining problem with I/O that I see now is that fstat() is pretty much useless, but I'm not sure how to fix that without tracking fd->filename mappings and using sceIoStat (there's no sceIoFstat). Any suggestions?
mrbrown
Site Admin
Posts: 1537
Joined: Sat Jan 17, 2004 11:24 am

Post by mrbrown »

Convert code to use stat() instead? :)
anhanguera
Posts: 31
Joined: Thu Aug 26, 2004 4:20 pm

Post by anhanguera »

hi,

if there is no sceIoFstat or, any other function like char * sceIoFname (SceUID fd) the only(?) choice is to use fd->filename map. and this will slow down(?) all the io; lock map, check/add/del io, unlock map.

there is something like int sceIoIoctl (fd, cmd, indata, inlen, outdata, outlen); any idea what are the commands are? i couldnot find any define in source tree. is it too childish to expect IOCTL_GET_FILENAME ;)

anhanguera.
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

mrbrown wrote:Convert code to use stat() instead? :)
Well, yeah :) But a working fstat would be nice too.
anhanguera wrote:if there is no sceIoFstat or, any other function like char * sceIoFname (SceUID fd) the only(?) choice is to use fd->filename map. and this will slow down(?) all the io; lock map, check/add/del io, unlock map.
It would only affect open(), fstat(), and close(). If we just have a fixed array of pointers, the overhead actually wouldn't be too bad (strdup for open, free for close, table lookup for fstat). Locking shouldn't be necessary. If we support 0<fd<1024, the mem overhead is only 4kb+filenames.
anhanguera wrote:there is something like int sceIoIoctl (fd, cmd, indata, inlen, outdata, outlen); any idea what are the commands are? i couldnot find any define in source tree. is it too childish to expect IOCTL_GET_FILENAME ;)
I'm sure there's something like IOCTL_GET_FILENAME or IOCTL_DO_FSTAT, but nobody outside of Sony knows what they are :)
anhanguera
Posts: 31
Joined: Thu Aug 26, 2004 4:20 pm

Post by anhanguera »

hi,
jimparis wrote: t would only affect open(), fstat(), and close(). If we just have a fixed array of pointers, the overhead actually wouldn't be too bad (strdup for open, free for close, table lookup for fstat). Locking shouldn't be necessary. If we support 0<fd<1024, the mem overhead is only 4kb+filenames.
this ugly patch does that, take a look.

Code: Select all

diff -U 3 -H -N newlib-psp/newlib/libc/sys/psp/libcglue.c newlib-1.13.0/newlib/libc/sys/psp/libcglue.c
--- newlib-psp/newlib/libc/sys/psp/libcglue.c   2005-10-05 20&#58;07&#58;36.000000000 +0300
+++ newlib-1.13.0/newlib/libc/sys/psp/libcglue.c        2005-10-05 20&#58;37&#58;07.000000000 +0300
@@ -40,6 +40,9 @@
 extern void __psp_init_cwd&#40;char *argv_0&#41;;
 extern int __psp_path_absolute&#40;const char *in, char *out, int len&#41;;

+#define __PSP_FILENO_MAX       1024
+extern char * __psp_filename_map&#91;__PSP_FILENO_MAX&#93;;
+
 #ifdef F_getcwd
 char *getcwd&#40;char *buf, size_t size&#41;
 &#123;
@@ -135,6 +138,7 @@
 #ifdef F__open
 int _open&#40;const char *name, int flags, int mode&#41;
 &#123;
+       int fd;
        int sce_flags;
        char dest&#91;MAXPATHLEN + 1&#93;;

@@ -163,8 +167,12 @@
        if &#40;flags & O_NONBLOCK&#41; &#123;
                sce_flags |= PSP_O_NBLOCK;
        &#125;
-
-       return sceIoOpen&#40;dest, sce_flags, mode&#41;;
+
+       fd = sceIoOpen&#40;dest, sce_flags, mode&#41;;
+       if &#40;&#40;fd >= 0&#41; && &#40;fd < __PSP_FILENO_MAX&#41;&#41; &#123;
+               __psp_filename_map&#91;fd&#93; = strdup&#40;dest&#41;;
+       &#125;
+       return fd;
 &#125;
 #endif

@@ -184,6 +192,13 @@
        if &#40;sce_fd < 0&#41; &#123;
                return -EBADF;
        &#125;
+
+       if &#40;&#40;sce_fd >= 0&#41; && &#40;sce_fd < __PSP_FILENO_MAX&#41;&#41; &#123;
+               if &#40;__psp_filename_map&#91;sce_fd&#93; != NULL&#41; &#123;
+                       free&#40;__psp_filename_map&#91;sce_fd&#93;&#41;;
+                       __psp_filename_map&#91;sce_fd&#93; = NULL;
+               &#125;
+       &#125;

        return sceIoClose&#40;sce_fd&#41;;
 &#125;
@@ -453,9 +468,12 @@
 #ifdef F__fstat
 int _fstat&#40;int fd, struct stat *sbuf&#41;
 &#123;
-        /* This is all Sony's newlib does, but should be improved */
-       sbuf->st_mode = S_IFCHR;
-       return 0;
+       if &#40;&#40;fd >= 0&#41; && &#40;fd < __PSP_FILENO_MAX&#41;&#41; &#123;
+               if &#40;__psp_filename_map&#91;fd&#93; != NULL&#41; &#123;
+                       return stat&#40;__psp_filename_map&#91;fd&#93;, sbuf&#41;;
+               &#125;
+       &#125;
+       return -1;
 &#125;
 #endif

@@ -619,6 +637,7 @@

        /* Initialize cwd from this program's path */
        __psp_init_cwd&#40;argv&#91;0&#93;&#41;;
+       memset&#40;__psp_filename_map, 0, sizeof&#40;char *&#41; * __PSP_FILENO_MAX&#41;;

        /* Initialize timezone from PSP configuration */
        int tzOffset = 0;
diff -U 3 -H -N newlib-psp/newlib/libc/sys/psp/pspcwd.c newlib-1.13.0/newlib/libc/sys/psp/pspcwd.c
--- newlib-psp/newlib/libc/sys/psp/pspcwd.c     2005-10-05 20&#58;07&#58;36.000000000 +0300
+++ newlib-1.13.0/newlib/libc/sys/psp/pspcwd.c  2005-10-05 20&#58;24&#58;37.000000000 +0300
@@ -19,6 +19,7 @@
 #include <pspiofilemgr.h>

 char __psp_cwd&#91;MAXPATHLEN + 1&#93; = &#123; 0 &#125;;
+char * __psp_filename_map&#91;1024&#93;;

 /* Set the current working directory &#40;CWD&#41; to the path where the module was launched. */
 void __psp_init_cwd&#40;char *argv_0&#41;
@@ -163,4 +164,3 @@
        if&#40;dr < 0&#41; dr = 0;
        return __psp_path_normalize&#40;out + dr, len - dr&#41;;
 &#125;
checked with (barrowed from cwd sample);

Code: Select all

#include <pspkernel.h>
#include <pspctrl.h>
#include <pspdebug.h>
#include <pspdisplay.h>
#include <psptypes.h>
#include <pspiofilemgr.h>

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/unistd.h>
#include <fcntl.h>

PSP_MODULE_INFO&#40;"CwdTest", 0, 1, 1&#41;;

#define printf pspDebugScreenPrintf

/* Exit callback */
int exit_callback&#40;int arg1, int arg2, void *common&#41;
&#123;
        sceKernelExitGame&#40;&#41;;

        return 0;
&#125;

/* Callback thread */
int CallbackThread&#40;SceSize args, void *argp&#41;
&#123;
        int cbid;

        cbid = sceKernelCreateCallback&#40;"Exit Callback", exit_callback, NULL&#41;;
        sceKernelRegisterExitCallback&#40;cbid&#41;;

        sceKernelSleepThreadCB&#40;&#41;;

        return 0;
&#125;

/* Sets up the callback thread and returns its thread id */
int SetupCallbacks&#40;void&#41;
&#123;
        int thid = 0;

        thid = sceKernelCreateThread&#40;"update_thread", CallbackThread, 0x11, 0xFA0, 0, 0&#41;;
        if&#40;thid >= 0&#41;
        &#123;
                sceKernelStartThread&#40;thid, 0, 0&#41;;
        &#125;

        return thid;
&#125;

int main&#40;void&#41;
&#123;
        int fd;
        struct stat st;

        pspDebugScreenInit&#40;&#41;;
        SetupCallbacks&#40;&#41;;

        stat&#40;"ms0&#58;/share/xynth/configs/xynth.conf", &st&#41;;
        printf&#40;"stat&#58; %lu, %lu, %lu, %u, %lu\n", st.st_ctime,
                                                 st.st_atime,
                                                 st.st_mtime,
                                                 st.st_mode,
                                                 st.st_size&#41;;
        fd = open&#40;"ms0&#58;/share/xynth/configs/xynth.conf", O_RDWR&#41;;
        printf&#40;"fd = %d\n", fd&#41;;

        st.st_ctime =
        st.st_atime =
        st.st_mtime =
        st.st_mode =
        st.st_size = 0;

        printf&#40;"fstat = %d\n", fstat&#40;fd, &st&#41;&#41;;
        printf&#40;"stat&#58; %lu, %lu, %lu, %u, %lu\n", st.st_ctime,
                                                 st.st_atime,
                                                 st.st_mtime,
                                                 st.st_mode,
                                                 st.st_size&#41;;
        close&#40;fd&#41;;
        printf&#40;"fstat = %d\n", fstat&#40;fd, &st&#41;&#41;;

        while &#40;1&#41; sleep &#40;1&#41;;
        return 0;
&#125;
mrbrown
Site Admin
Posts: 1537
Joined: Sat Jan 17, 2004 11:24 am

Post by mrbrown »

Correct me if I'm wrong, but I thought sceIoOpen() returned a UID? How is it that the values returned are below 1024?
mrbrown
Site Admin
Posts: 1537
Joined: Sat Jan 17, 2004 11:24 am

Post by mrbrown »

Bah, nevermind, it doesn't return a real UID even though the return type is SceUID.
anhanguera
Posts: 31
Joined: Thu Aug 26, 2004 4:20 pm

Post by anhanguera »

hi,

i confuses me, too ;)

but i tried this senorio below;

sceIoOpen() -> fd = 3;
sceIoOpen() -> fd = 4;
sceIoClose(4)
sceIoOpen() -> fd = 4
sceIoClose(4)
sceIoClose(3)
sceIoOpen() -> fd = 3;
sceIoOpen() -> fd = 4;

as seen here, if we do not open more than 1021 files fd will always smaller then 1024. will be?

anhanguera.
mrbrown
Site Admin
Posts: 1537
Joined: Sat Jan 17, 2004 11:24 am

Post by mrbrown »

Yes, it works exactly the same as open() and sceOpen() on the PS2. My confusion was that the headers say sceIoOpen() returns a SceUID, which is a special type of value used by the PSP kernel. UIDs are never below 1024 :).

The headers should probably be updated to reflect that sceIoOpen() (and related calls) return an int instead of SceUID.
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

What to do with fd < 3 should probably be clarified and cleaned up a bit. Why does _close() treat them differently? That code will behave pretty badly if you can close(0) and then have open() return 0 for some other file. And if they do still refer to the "real" stdin/stdout/stderr, _fstat() should return S_IFCHR. Similarly, isatty()=1 only for those. We could initialize them in the filename map to an empty string to indicate that they're the preexisting stdio streams, and that will get automatically cleared if they're ever closed and reopened as something else.

anhanguera, you should talk to Neovanglist or Oobles on IRC or via PM to get svn commit access.
anhanguera
Posts: 31
Joined: Thu Aug 26, 2004 4:20 pm

Post by anhanguera »

hi,

S_IFCHR and isatty() thing is OK with the patch(below). but assumes that user will not open a file called

Code: Select all

"  __PSP_STDIO"
there is;

Code: Select all

if &#40;fd == STDIN_FILENO&#41; &#123;
        sce_fd = sceKernelStdin&#40;&#41;;
&#125; else if &#40;fd == STDOUT_FILENO&#41; &#123;
        sce_fd = sceKernelStdout&#40;&#41;;
&#125; else if &#40;fd == STDERR_FILENO&#41; &#123;
        sce_fd = sceKernelStderr&#40;&#41;;
&#125;
all over the code, with these close(0); (fd = open(file, ..) == 0); read/write/lseek(fd) will never work(?) or am i missing something?
maybe newly opened user file fd`s can be forced to be >= 3, and closing stdin/out/err is not allowed.

Code: Select all

diff -U 3 -H -N newlib-psp/newlib/libc/sys/psp/libcglue.c newlib-1.13.0/newlib/libc/sys/psp/libcglue.c
--- newlib-psp/newlib/libc/sys/psp/libcglue.c   2005-10-05 20&#58;07&#58;36.000000000 +0300
+++ newlib-1.13.0/newlib/libc/sys/psp/libcglue.c        2005-10-06 00&#58;00&#58;56.000000000 +0300
@@ -40,6 +40,9 @@
 extern void __psp_init_cwd&#40;char *argv_0&#41;;
 extern int __psp_path_absolute&#40;const char *in, char *out, int len&#41;;

+#define __PSP_FILENO_MAX       1024
+extern char * __psp_filename_map&#91;__PSP_FILENO_MAX&#93;;
+
 #ifdef F_getcwd
 char *getcwd&#40;char *buf, size_t size&#41;
 &#123;
@@ -135,6 +138,7 @@
 #ifdef F__open
 int _open&#40;const char *name, int flags, int mode&#41;
 &#123;
+       int fd;
        int sce_flags;
        char dest&#91;MAXPATHLEN + 1&#93;;

@@ -163,8 +167,12 @@
        if &#40;flags & O_NONBLOCK&#41; &#123;
                sce_flags |= PSP_O_NBLOCK;
        &#125;
-
-       return sceIoOpen&#40;dest, sce_flags, mode&#41;;
+
+       fd = sceIoOpen&#40;dest, sce_flags, mode&#41;;
+       if &#40;&#40;fd >= 0&#41; && &#40;fd < __PSP_FILENO_MAX&#41;&#41; &#123;
+               __psp_filename_map&#91;fd&#93; = strdup&#40;dest&#41;;
+       &#125;
+       return fd;
 &#125;
 #endif

@@ -184,6 +192,13 @@
        if &#40;sce_fd < 0&#41; &#123;
                return -EBADF;
        &#125;
+
+       if &#40;&#40;sce_fd >= 0&#41; && &#40;sce_fd < __PSP_FILENO_MAX&#41;&#41; &#123;
+               if &#40;__psp_filename_map&#91;sce_fd&#93; != NULL&#41; &#123;
+                       free&#40;__psp_filename_map&#91;sce_fd&#93;&#41;;
+                       __psp_filename_map&#91;sce_fd&#93; = NULL;
+               &#125;
+       &#125;

        return sceIoClose&#40;sce_fd&#41;;
 &#125;
@@ -453,16 +468,34 @@
 #ifdef F__fstat
 int _fstat&#40;int fd, struct stat *sbuf&#41;
 &#123;
-        /* This is all Sony's newlib does, but should be improved */
-       sbuf->st_mode = S_IFCHR;
-       return 0;
+       if &#40;&#40;fd >= 0&#41; && &#40;fd < __PSP_FILENO_MAX&#41;&#41; &#123;
+               if &#40;__psp_filename_map&#91;fd&#93; != NULL&#41; &#123;
+                       if &#40;strcmp&#40;__psp_filename_map&#91;fd&#93;, "  __PSP_STDIO"&#41; == 0&#41; &#123;
+                               memset&#40;sbuf, '\0', sizeof&#40;struct stat&#41;&#41;;
+                               sbuf->st_mode = S_IFCHR;
+                               return 0;
+                       &#125; else &#123;
+                               return stat&#40;__psp_filename_map&#91;fd&#93;, sbuf&#41;;
+                       &#125;
+               &#125;
+       &#125;
+       return -1;
 &#125;
 #endif

 #ifdef F_isatty
 int isatty&#40;int fd&#41;
 &#123;
-       return 1;
+       if &#40;&#40;fd >= 0&#41; && &#40;fd < __PSP_FILENO_MAX&#41;&#41; &#123;
+               if &#40;__psp_filename_map&#91;fd&#93; != NULL&#41; &#123;
+                       if &#40;strcmp&#40;__psp_filename_map&#91;fd&#93;, "  __PSP_STDIO"&#41; == 0&#41; &#123;
+                               return 1;
+                       &#125; else &#123;
+                               return 0;
+                       &#125;
+               &#125;
+       &#125;
+       return 0;
 &#125;
 #endif

@@ -620,6 +653,12 @@
        /* Initialize cwd from this program's path */
        __psp_init_cwd&#40;argv&#91;0&#93;&#41;;

+       /* Initialize filename map */
+       memset&#40;__psp_filename_map, 0, sizeof&#40;char *&#41; * __PSP_FILENO_MAX&#41;;
+       __psp_filename_map&#91;0&#93; = strdup&#40;"  __PSP_STDIO"&#41;;
+       __psp_filename_map&#91;1&#93; = strdup&#40;"  __PSP_STDIO"&#41;;
+       __psp_filename_map&#91;2&#93; = strdup&#40;"  __PSP_STDIO"&#41;;
+
        /* Initialize timezone from PSP configuration */
        int tzOffset = 0;
        sceUtilityGetSystemParamInt&#40;PSP_SYSTEMPARAM_ID_INT_TIMEZONE, &tzOffset&#41;;
diff -U 3 -H -N newlib-psp/newlib/libc/sys/psp/pspcwd.c newlib-1.13.0/newlib/libc/sys/psp/pspcwd.c
--- newlib-psp/newlib/libc/sys/psp/pspcwd.c     2005-10-05 20&#58;07&#58;36.000000000 +0300
+++ newlib-1.13.0/newlib/libc/sys/psp/pspcwd.c  2005-10-05 20&#58;24&#58;37.000000000 +0300
@@ -19,6 +19,7 @@
 #include <pspiofilemgr.h>

 char __psp_cwd&#91;MAXPATHLEN + 1&#93; = &#123; 0 &#125;;
+char * __psp_filename_map&#91;1024&#93;;

 /* Set the current working directory &#40;CWD&#41; to the path where the module was launched. */
 void __psp_init_cwd&#40;char *argv_0&#41;
@@ -163,4 +164,3 @@
        if&#40;dr < 0&#41; dr = 0;
        return __psp_path_normalize&#40;out + dr, len - dr&#41;;
 &#125;
anhanguera

ps: may be i should talk for svn commit access after getting things clear, i do not want to f*ck the code up. ;)
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

I suggest we just get rid of the sce_fd and sceKernelStdin(), sceKernelStdout(), and sceKernelStderr() stuff completely. Those functions just return 0, 1, and 2 anyway, even if something like pspDebugInstallStderrHandler() has been called.

You should get access.. every one of your patches has looked fine, and in the worst case we can always roll back to an earlier version if you do mess something up :)
anhanguera
Posts: 31
Joined: Thu Aug 26, 2004 4:20 pm

Post by anhanguera »

hi again,

sceKernelStdin() returns always "0", even after close(0). anyway, here is the new patch; removed if (fd == ...) fd = sceKernelStdin(); ... stuff, and changed initialization.

anhanguera.

Code: Select all

diff -U 3 -H -d -r -N newlib-psp/newlib/libc/sys/psp/libcglue.c newlib-1.13.0/newlib/libc/sys/psp/libcglue.c
--- newlib-psp/newlib/libc/sys/psp/libcglue.c   Thu Oct  6 09&#58;21&#58;00 2005
+++ newlib-1.13.0/newlib/libc/sys/psp/libcglue.c        Thu Oct  6 10&#58;46&#58;46 2005
@@ -40,6 +40,9 @@
 extern void __psp_init_cwd&#40;char *argv_0&#41;;
 extern int __psp_path_absolute&#40;const char *in, char *out, int len&#41;;

+#define __PSP_FILENO_MAX 1024
+extern char * __psp_filename_map&#91;__PSP_FILENO_MAX&#93;;
+
 #ifdef F_getcwd
 char *getcwd&#40;char *buf, size_t size&#41;
 &#123;
@@ -135,6 +138,7 @@
 #ifdef F__open
 int _open&#40;const char *name, int flags, int mode&#41;
 &#123;
+       int fd;
        int sce_flags;
        char dest&#91;MAXPATHLEN + 1&#93;;

@@ -164,92 +168,63 @@
                sce_flags |= PSP_O_NBLOCK;
        &#125;

-       return sceIoOpen&#40;dest, sce_flags, mode&#41;;
+       fd = sceIoOpen&#40;dest, sce_flags, mode&#41;;
+       if &#40;&#40;fd >= 0&#41; && &#40;fd < __PSP_FILENO_MAX&#41;&#41; &#123;
+               __psp_filename_map&#91;fd&#93; = strdup&#40;dest&#41;;
+       &#125;
+       return fd;
 &#125;
 #endif

 #ifdef F__close
 int _close&#40;int fd&#41;
 &#123;
-       int sce_fd = fd;
-
-       if &#40;fd == STDIN_FILENO&#41; &#123;
-               sce_fd = sceKernelStdin&#40;&#41;;
-       &#125; else if &#40;fd == STDOUT_FILENO&#41; &#123;
-               sce_fd = sceKernelStdout&#40;&#41;;
-       &#125; else if &#40;fd == STDERR_FILENO&#41; &#123;
-               sce_fd == sceKernelStderr&#40;&#41;;
-       &#125;
-
-       if &#40;sce_fd < 0&#41; &#123;
+       if &#40;fd < 0&#41; &#123;
                return -EBADF;
        &#125;
+
+       if &#40;&#40;fd >= 0&#41; && &#40;fd < __PSP_FILENO_MAX&#41;&#41; &#123;
+               if &#40;__psp_filename_map&#91;fd&#93; != NULL&#41; &#123;
+                       free&#40;__psp_filename_map&#91;fd&#93;&#41;;
+                       __psp_filename_map&#91;fd&#93; = NULL;
+               &#125;
+       &#125;

-       return sceIoClose&#40;sce_fd&#41;;
+       return sceIoClose&#40;fd&#41;;
 &#125;
 #endif

 #ifdef F__read
 int _read&#40;int fd, void *buf, size_t size&#41;
 &#123;
-       int sce_fd = fd;
-
-       if &#40;fd == STDIN_FILENO&#41; &#123;
-               sce_fd = sceKernelStdin&#40;&#41;;
-       &#125; else if &#40;fd == STDOUT_FILENO&#41; &#123;
-               sce_fd = sceKernelStdout&#40;&#41;;
-       &#125; else if &#40;fd == STDERR_FILENO&#41; &#123;
-               sce_fd = sceKernelStderr&#40;&#41;;
-       &#125;
-
-       if &#40;sce_fd < 0&#41; &#123;
+       if &#40;fd < 0&#41; &#123;
                return -EBADF;
        &#125;

-       return sceIoRead&#40;sce_fd, buf, size&#41;;
+       return sceIoRead&#40;fd, buf, size&#41;;
 &#125;
 #endif

 #ifdef F__write
 int _write&#40;int fd, const void *buf, size_t size&#41;
 &#123;
-       int sce_fd = fd;
-
-       if &#40;fd == STDIN_FILENO&#41; &#123;
-               sce_fd = sceKernelStdin&#40;&#41;;
-       &#125; else if &#40;fd == STDOUT_FILENO&#41; &#123;
-               sce_fd = sceKernelStdout&#40;&#41;;
-       &#125; else if &#40;fd == STDERR_FILENO&#41; &#123;
-               sce_fd = sceKernelStderr&#40;&#41;;
-       &#125;
-
-       if &#40;sce_fd < 0&#41; &#123;
+       if &#40;fd < 0&#41; &#123;
                return -EBADF;
        &#125;

-       return sceIoWrite&#40;sce_fd, buf, size&#41;;
+       return sceIoWrite&#40;fd, buf, size&#41;;
 &#125;
 #endif

 #ifdef F__lseek
 off_t _lseek&#40;int fd, off_t offset, int whence&#41;
 &#123;
-       int sce_fd = fd;
-
-       if &#40;fd == STDIN_FILENO&#41; &#123;
-               sce_fd = sceKernelStdin&#40;&#41;;
-       &#125; else if &#40;fd == STDOUT_FILENO&#41; &#123;
-               sce_fd = sceKernelStdout&#40;&#41;;
-       &#125; else if &#40;fd == STDERR_FILENO&#41; &#123;
-               sce_fd = sceKernelStderr&#40;&#41;;
-       &#125;
-
-       if &#40;sce_fd < 0&#41; &#123;
+       if &#40;fd < 0&#41; &#123;
                return -EBADF;
        &#125;

        /* We don't have to do anything with the whence argument because SEEK_* == PSP_SEEK_*. */
-       return &#40;off_t&#41; sceIoLseek&#40;sce_fd, offset, whence&#41;;
+       return &#40;off_t&#41; sceIoLseek&#40;fd, offset, whence&#41;;
 &#125;
 #endif

@@ -453,16 +428,34 @@
 #ifdef F__fstat
 int _fstat&#40;int fd, struct stat *sbuf&#41;
 &#123;
-        /* This is all Sony's newlib does, but should be improved */
-       sbuf->st_mode = S_IFCHR;
-       return 0;
+       if &#40;&#40;fd >= 0&#41; && &#40;fd < __PSP_FILENO_MAX&#41;&#41; &#123;
+               if &#40;__psp_filename_map&#91;fd&#93; != NULL&#41; &#123;
+                       if &#40;strcmp&#40;__psp_filename_map&#91;fd&#93;, "  __PSP_STDIO"&#41; == 0&#41; &#123;
+                               memset&#40;sbuf, '\0', sizeof&#40;struct stat&#41;&#41;;
+                               sbuf->st_mode = S_IFCHR;
+                               return 0;
+                       &#125; else &#123;
+                               return stat&#40;__psp_filename_map&#91;fd&#93;, sbuf&#41;;
+                       &#125;
+               &#125;
+       &#125;
+       return -1;
 &#125;
 #endif

 #ifdef F_isatty
 int isatty&#40;int fd&#41;
 &#123;
-       return 1;
+       if &#40;&#40;fd >= 0&#41; && &#40;fd < __PSP_FILENO_MAX&#41;&#41; &#123;
+               if &#40;__psp_filename_map&#91;fd&#93; != NULL&#41; &#123;
+                       if &#40;strcmp&#40;__psp_filename_map&#91;fd&#93;, "  __PSP_STDIO"&#41; == 0&#41; &#123;
+                               return 1;
+                       &#125; else &#123;
+                               return 0;
+                       &#125;
+               &#125;
+       &#125;
+       return 0;
 &#125;
 #endif

@@ -615,10 +608,26 @@
 */
 void __psp_libc_init&#40;int argc, char *argv&#91;&#93;&#41;
 &#123;
-       &#40;void&#41;argc;
+       int fd;
+       &#40;void&#41; argc;

        /* Initialize cwd from this program's path */
        __psp_init_cwd&#40;argv&#91;0&#93;&#41;;
+
+       /* Initialize filenamap */
+       memset&#40;__psp_filename_map, '\0', sizeof&#40;char *&#41; * __PSP_FILENO_MAX&#41;;
+       fd = sceKernelStdin&#40;&#41;;
+       if &#40;&#40;fd >= 0&#41; && &#40;fd < __PSP_FILENO_MAX&#41;&#41; &#123;
+               __psp_filename_map&#91;fd&#93; = strdup&#40;"  __PSP_STDIO"&#41;;
+       &#125;
+       fd = sceKernelStdout&#40;&#41;;
+       if &#40;&#40;fd >= 0&#41; && &#40;fd < __PSP_FILENO_MAX&#41;&#41; &#123;
+               __psp_filename_map&#91;fd&#93; = strdup&#40;"  __PSP_STDIO"&#41;;
+       &#125;
+       fd = sceKernelStderr&#40;&#41;;
+       if &#40;&#40;fd >= 0&#41; && &#40;fd < __PSP_FILENO_MAX&#41;&#41; &#123;
+               __psp_filename_map&#91;fd&#93; = strdup&#40;"  __PSP_STDIO"&#41;;
+       &#125;

        /* Initialize timezone from PSP configuration */
        int tzOffset = 0;
diff -U 3 -H -d -r -N newlib-psp/newlib/libc/sys/psp/pspcwd.c newlib-1.13.0/newlib/libc/sys/psp/pspcwd.c
--- newlib-psp/newlib/libc/sys/psp/pspcwd.c     Thu Oct  6 09&#58;21&#58;00 2005
+++ newlib-1.13.0/newlib/libc/sys/psp/pspcwd.c  Thu Oct  6 10&#58;06&#58;02 2005
@@ -19,6 +19,7 @@
 #include <pspiofilemgr.h>

 char __psp_cwd&#91;MAXPATHLEN + 1&#93; = &#123; 0 &#125;;
+char * __psp_filename_map&#91;1024&#93;;

 /* Set the current working directory &#40;CWD&#41; to the path where the module was launched. */
 void __psp_init_cwd&#40;char *argv_0&#41;
ps: i`ve asked oobles for svn access via pm, but if not given you or someone else can apply this, no prob. ;)
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

Looks good and works great; I've applied it to rev 1124. Thanks again for your help.
Post Reply