Skip to content

Commit 9ee6942

Browse files
ccawley2011slouken
authored andcommitted
Improve RISC OS implementations of SDL_GetBasePath and SDL_GetPrefPath
1 parent 3db898c commit 9ee6942

File tree

1 file changed

+144
-26
lines changed

1 file changed

+144
-26
lines changed

src/filesystem/riscos/SDL_sysfilesystem.c

Lines changed: 144 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,28 +25,144 @@
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

36133
char *
37134
SDL_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

43160
char *
44161
SDL_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

Comments
 (0)