2525/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2626/* System dependent filesystem routines */
2727
28- #include <errno.h>
29- #include <sys/stat.h>
28+ #include <kernel.h>
29+ #include <swis.h>
30+ #include <unixlib/local.h>
3031
3132#include "SDL_error.h"
3233#include "SDL_stdinc.h"
3334#include "SDL_filesystem.h"
34- #include "SDL_rwops.h"
35+
36+ /* Wrapper around __unixify_std that uses SDL's memory allocators */
37+ static char *
38+ SDL_unixify_std (const char * ro_path , char * buffer , size_t buf_len , int filetype )
39+ {
40+ const char * const in_buf = buffer ; /* = NULL if we malloc the buffer. */
41+
42+ if (!buffer ) {
43+ /* This matches the logic in __unixify, with an additional byte for the
44+ * extra path separator.
45+ */
46+ buf_len = SDL_strlen (ro_path ) + 14 + 1 ;
47+ buffer = SDL_malloc (buf_len );
48+
49+ if (!buffer ) {
50+ SDL_OutOfMemory ();
51+ return NULL ;
52+ }
53+ }
54+
55+ if (!__unixify_std (ro_path , buffer , buf_len , filetype )) {
56+ if (!in_buf )
57+ SDL_free (buffer );
58+
59+ SDL_SetError ("Could not convert '%s' to a Unix-style path" , ro_path );
60+ return NULL ;
61+ }
62+
63+ /* HACK: It's necessary to add an extra path separator here since SDL's API
64+ * requires it, however paths with trailing separators aren't normally valid
65+ * on RISC OS.
66+ */
67+ if (__get_riscosify_control () & __RISCOSIFY_NO_PROCESS )
68+ SDL_strlcat (buffer , "." , buf_len );
69+ else
70+ SDL_strlcat (buffer , "/" , buf_len );
71+
72+ return buffer ;
73+ }
74+
75+ static char *
76+ canonicalisePath (const char * path , const char * pathVar )
77+ {
78+ _kernel_oserror * error ;
79+ _kernel_swi_regs regs ;
80+ char * buf ;
81+
82+ regs .r [0 ] = 37 ;
83+ regs .r [1 ] = (int )path ;
84+ regs .r [2 ] = 0 ;
85+ regs .r [3 ] = (int )pathVar ;
86+ regs .r [4 ] = 0 ;
87+ regs .r [5 ] = 0 ;
88+ error = _kernel_swi (OS_FSControl , & regs , & regs );
89+ if (error ) {
90+ SDL_SetError ("Couldn't canonicalise path: %s" , error -> errmess );
91+ return NULL ;
92+ }
93+
94+ regs .r [5 ] = 1 - regs .r [5 ];
95+ buf = SDL_malloc (regs .r [5 ]);
96+ if (!buf ) {
97+ SDL_OutOfMemory ();
98+ return NULL ;
99+ }
100+ regs .r [2 ] = (int )buf ;
101+ error = _kernel_swi (OS_FSControl , & regs , & regs );
102+ if (error ) {
103+ SDL_SetError ("Couldn't canonicalise path: %s" , error -> errmess );
104+ SDL_free (buf );
105+ return NULL ;
106+ }
107+
108+ return buf ;
109+ }
110+
111+ static _kernel_oserror *
112+ createDirectoryRecursive (char * path )
113+ {
114+ char * ptr = NULL ;
115+ _kernel_oserror * error ;
116+ _kernel_swi_regs regs ;
117+ regs .r [0 ] = 8 ;
118+ regs .r [1 ] = (int )path ;
119+ regs .r [2 ] = 0 ;
120+
121+ for (ptr = path + 1 ; * ptr ; ptr ++ ) {
122+ if (* ptr == '.' ) {
123+ * ptr = '\0' ;
124+ error = _kernel_swi (OS_File , & regs , & regs );
125+ * ptr = '.' ;
126+ if (error != NULL )
127+ return error ;
128+ }
129+ }
130+ return _kernel_swi (OS_File , & regs , & regs );
131+ }
35132
36133char *
37134SDL_GetBasePath (void )
38135{
39- SDL_Unsupported ();
40- return NULL ;
136+ _kernel_swi_regs regs ;
137+ _kernel_oserror * error ;
138+ char * canon , * ptr , * retval ;
139+
140+ error = _kernel_swi (OS_GetEnv , & regs , & regs );
141+ if (error ) {
142+ return NULL ;
143+ }
144+
145+ canon = canonicalisePath ((const char * )regs .r [0 ], "Run$Path" );
146+ if (!canon ) {
147+ return NULL ;
148+ }
149+
150+ /* chop off filename. */
151+ ptr = SDL_strrchr (canon , '.' );
152+ if (ptr != NULL )
153+ * ptr = '\0' ;
154+
155+ retval = SDL_unixify_std (canon , NULL , 0 , __RISCOSIFY_FILETYPE_NOTSPECIFIED );
156+ SDL_free (canon );
157+ return retval ;
41158}
42159
43160char *
44161SDL_GetPrefPath (const char * org , const char * app )
45162{
46- const char * prefix = "/<Choices$Write>/" ;
47- char * retval = NULL ;
48- char * ptr = NULL ;
49- size_t len = 0 ;
163+ char * canon , * dir , * retval ;
164+ size_t len ;
165+ _kernel_oserror * error ;
50166
51167 if (!app ) {
52168 SDL_InvalidParamError ("app" );
@@ -56,34 +172,36 @@ SDL_GetPrefPath(const char *org, const char *app)
56172 org = "" ;
57173 }
58174
59- len = SDL_strlen (prefix ) + SDL_strlen (org ) + SDL_strlen (app ) + 3 ;
60- retval = (char * ) SDL_malloc (len );
61- if (!retval ) {
175+ canon = canonicalisePath ("<Choices$Write>" , "Run$Path" );
176+ if (!canon ) {
177+ return NULL ;
178+ }
179+
180+ len = SDL_strlen (canon ) + SDL_strlen (org ) + SDL_strlen (app ) + 4 ;
181+ dir = (char * ) SDL_malloc (len );
182+ if (!dir ) {
62183 SDL_OutOfMemory ();
184+ free (canon );
63185 return NULL ;
64186 }
65187
66188 if (* org ) {
67- SDL_snprintf (retval , len , "%s%s/%s/ " , prefix , org , app );
189+ SDL_snprintf (dir , len , "%s.%s.%s " , canon , org , app );
68190 } else {
69- SDL_snprintf (retval , len , "%s%s/ " , prefix , app );
191+ SDL_snprintf (dir , len , "%s.%s " , canon , app );
70192 }
71193
72- for (ptr = retval + 1 ; * ptr ; ptr ++ ) {
73- if (* ptr == '/' ) {
74- * ptr = '\0' ;
75- if (mkdir (retval , 0700 ) != 0 && errno != EEXIST )
76- goto error ;
77- * ptr = '/' ;
78- }
79- }
80- if (mkdir (retval , 0700 ) != 0 && errno != EEXIST ) {
81- error :
82- SDL_SetError ("Couldn't create directory '%s': '%s'" , retval , strerror (errno ));
83- SDL_free (retval );
194+ SDL_free (canon );
195+
196+ error = createDirectoryRecursive (dir );
197+ if (error != NULL ) {
198+ SDL_SetError ("Couldn't create directory: %s" , error -> errmess );
199+ SDL_free (dir );
84200 return NULL ;
85201 }
86202
203+ retval = SDL_unixify_std (dir , NULL , 0 , __RISCOSIFY_FILETYPE_NOTSPECIFIED );
204+ SDL_free (dir );
87205 return retval ;
88206}
89207
0 commit comments