diff options
Diffstat (limited to 'firmware/common/rbpaths.c')
-rw-r--r-- | firmware/common/rbpaths.c | 173 |
1 files changed, 121 insertions, 52 deletions
diff --git a/firmware/common/rbpaths.c b/firmware/common/rbpaths.c index a188cf6642..8efb6dd238 100644 --- a/firmware/common/rbpaths.c +++ b/firmware/common/rbpaths.c | |||
@@ -23,6 +23,9 @@ | |||
23 | #include <stdio.h> /* snprintf */ | 23 | #include <stdio.h> /* snprintf */ |
24 | #include <stdlib.h> | 24 | #include <stdlib.h> |
25 | #include <stdarg.h> | 25 | #include <stdarg.h> |
26 | #include <sys/stat.h> | ||
27 | #include <time.h> | ||
28 | #include <unistd.h> | ||
26 | #include "config.h" | 29 | #include "config.h" |
27 | #include "rbpaths.h" | 30 | #include "rbpaths.h" |
28 | #include "file.h" /* MAX_PATH */ | 31 | #include "file.h" /* MAX_PATH */ |
@@ -31,39 +34,34 @@ | |||
31 | #include "string-extra.h" | 34 | #include "string-extra.h" |
32 | #include "filefuncs.h" | 35 | #include "filefuncs.h" |
33 | 36 | ||
37 | /* In this file we need the actual OS library functions, not the shadowed | ||
38 | * wrapper used within Rockbox' application code (except SDL adds | ||
39 | * another layer) */ | ||
34 | #undef open | 40 | #undef open |
35 | #undef creat | 41 | #undef creat |
36 | #undef remove | 42 | #undef remove |
37 | #undef rename | 43 | #undef rename |
38 | #undef opendir | 44 | #undef opendir |
45 | #undef closedir | ||
46 | #undef readdir | ||
39 | #undef mkdir | 47 | #undef mkdir |
40 | #undef rmdir | 48 | #undef rmdir |
49 | #undef dirent | ||
50 | #undef DIR | ||
41 | 51 | ||
42 | |||
43 | #if (CONFIG_PLATFORM & PLATFORM_ANDROID) || defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) && !defined(__PCTOOL__) | ||
44 | #include "dir-target.h" | ||
45 | #define opendir _opendir | ||
46 | #define mkdir _mkdir | ||
47 | #if (CONFIG_PLATFORM & PLATFORM_ANDROID) | 52 | #if (CONFIG_PLATFORM & PLATFORM_ANDROID) |
48 | static const char rbhome[] = "/sdcard"; | 53 | static const char rbhome[] = "/sdcard"; |
49 | #endif | 54 | #endif |
50 | #elif (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO|PLATFORM_PANDORA)) && !defined(__PCTOOL__) | 55 | #if (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO|PLATFORM_PANDORA)) && !defined(__PCTOOL__) |
51 | #define open sim_open | ||
52 | #define remove sim_remove | ||
53 | #define rename sim_rename | ||
54 | #define opendir sim_opendir | ||
55 | #define mkdir sim_mkdir | ||
56 | #define rmdir sim_rmdir | ||
57 | extern int sim_open(const char* name, int o, ...); | ||
58 | extern int sim_remove(const char* name); | ||
59 | extern int sim_rename(const char* old, const char* new); | ||
60 | extern DIR* sim_opendir(const char* name); | ||
61 | extern int sim_mkdir(const char* name); | ||
62 | extern int sim_rmdir(const char* name); | ||
63 | const char *rbhome; | 56 | const char *rbhome; |
64 | #endif | 57 | #endif |
65 | 58 | ||
66 | #if !(defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1)) && !defined(__PCTOOL__) | 59 | #if !(defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1)) && !defined(__PCTOOL__) |
60 | /* Special dirs are user-accessible (and user-writable) dirs which take priority | ||
61 | * over the ones where Rockbox is installed to. Classic example would be | ||
62 | * $HOME/.config/rockbox.org vs /usr/share/rockbox */ | ||
63 | #define HAVE_SPECIAL_DIRS | ||
64 | #endif | ||
67 | 65 | ||
68 | /* flags for get_user_file_path() */ | 66 | /* flags for get_user_file_path() */ |
69 | /* whether you need write access to that file/dir, especially true | 67 | /* whether you need write access to that file/dir, especially true |
@@ -72,12 +70,13 @@ const char *rbhome; | |||
72 | /* file or directory? */ | 70 | /* file or directory? */ |
73 | #define IS_FILE (1<<1) | 71 | #define IS_FILE (1<<1) |
74 | 72 | ||
73 | #ifdef HAVE_SPECIAL_DIRS | ||
75 | void paths_init(void) | 74 | void paths_init(void) |
76 | { | 75 | { |
77 | /* make sure $HOME/.config/rockbox.org exists, it's needed for config.cfg */ | 76 | /* make sure $HOME/.config/rockbox.org exists, it's needed for config.cfg */ |
78 | #if (CONFIG_PLATFORM & PLATFORM_ANDROID) | 77 | #if (CONFIG_PLATFORM & PLATFORM_ANDROID) |
79 | mkdir("/sdcard/rockbox"); | 78 | mkdir("/sdcard/rockbox", 0777); |
80 | mkdir("/sdcard/rockbox/rocks.data"); | 79 | mkdir("/sdcard/rockbox/rocks.data", 0777); |
81 | #else | 80 | #else |
82 | char config_dir[MAX_PATH]; | 81 | char config_dir[MAX_PATH]; |
83 | 82 | ||
@@ -94,13 +93,14 @@ void paths_init(void) | |||
94 | 93 | ||
95 | rbhome = home; | 94 | rbhome = home; |
96 | snprintf(config_dir, sizeof(config_dir), "%s/.config", home); | 95 | snprintf(config_dir, sizeof(config_dir), "%s/.config", home); |
97 | mkdir(config_dir); | 96 | mkdir(config_dir, 0777); |
98 | snprintf(config_dir, sizeof(config_dir), "%s/.config/rockbox.org", home); | 97 | snprintf(config_dir, sizeof(config_dir), "%s/.config/rockbox.org", home); |
99 | mkdir(config_dir); | 98 | mkdir(config_dir, 0777); |
100 | /* Plugin data directory */ | 99 | /* Plugin data directory */ |
101 | snprintf(config_dir, sizeof(config_dir), "%s/.config/rockbox.org/rocks.data", home); | 100 | snprintf(config_dir, sizeof(config_dir), "%s/.config/rockbox.org/rocks.data", home); |
102 | mkdir(config_dir); | 101 | mkdir(config_dir, 0777); |
103 | #endif | 102 | #endif |
103 | |||
104 | } | 104 | } |
105 | 105 | ||
106 | static bool try_path(const char* filename, unsigned flags) | 106 | static bool try_path(const char* filename, unsigned flags) |
@@ -173,6 +173,21 @@ static const char* handle_special_dirs(const char* dir, unsigned flags, | |||
173 | return dir; | 173 | return dir; |
174 | } | 174 | } |
175 | 175 | ||
176 | #else /* !HAVE_SPECIAL_DIRS */ | ||
177 | |||
178 | #ifndef paths_init | ||
179 | void paths_init(void) { } | ||
180 | #endif | ||
181 | |||
182 | static const char* handle_special_dirs(const char* dir, unsigned flags, | ||
183 | char *buf, const size_t bufsize) | ||
184 | { | ||
185 | (void) flags; (void) buf; (void) bufsize; | ||
186 | return dir; | ||
187 | } | ||
188 | |||
189 | #endif | ||
190 | |||
176 | int app_open(const char *name, int o, ...) | 191 | int app_open(const char *name, int o, ...) |
177 | { | 192 | { |
178 | char realpath[MAX_PATH]; | 193 | char realpath[MAX_PATH]; |
@@ -215,48 +230,102 @@ int app_rename(const char *old, const char *new) | |||
215 | return rename(final_old, final_new); | 230 | return rename(final_old, final_new); |
216 | } | 231 | } |
217 | 232 | ||
218 | DIR *app_opendir(const char *name) | 233 | /* need to wrap around DIR* because we need to save the parent's |
234 | * directory path in order to determine dirinfo, required to implement | ||
235 | * get_dir_info() */ | ||
236 | struct __dir { | ||
237 | DIR *dir; | ||
238 | char path[]; | ||
239 | }; | ||
240 | |||
241 | struct dirinfo dir_get_info(DIR* _parent, struct dirent *dir) | ||
242 | { | ||
243 | struct __dir *parent = (struct __dir*)_parent; | ||
244 | struct stat s; | ||
245 | struct tm *tm = NULL; | ||
246 | struct dirinfo ret; | ||
247 | char path[MAX_PATH]; | ||
248 | |||
249 | snprintf(path, sizeof(path), "%s/%s", parent->path, dir->d_name); | ||
250 | memset(&ret, 0, sizeof(ret)); | ||
251 | |||
252 | if (!stat(path, &s)) | ||
253 | { | ||
254 | if (S_ISDIR(s.st_mode)) | ||
255 | { | ||
256 | ret.attribute = ATTR_DIRECTORY; | ||
257 | } | ||
258 | ret.size = s.st_size; | ||
259 | tm = localtime(&(s.st_mtime)); | ||
260 | } | ||
261 | |||
262 | if (!lstat(path, &s) && S_ISLNK(s.st_mode)) | ||
263 | { | ||
264 | ret.attribute |= ATTR_LINK; | ||
265 | } | ||
266 | |||
267 | if (tm) | ||
268 | { | ||
269 | ret.wrtdate = ((tm->tm_year - 80) << 9) | | ||
270 | ((tm->tm_mon + 1) << 5) | | ||
271 | tm->tm_mday; | ||
272 | ret.wrttime = (tm->tm_hour << 11) | | ||
273 | (tm->tm_min << 5) | | ||
274 | (tm->tm_sec >> 1); | ||
275 | } | ||
276 | |||
277 | return ret; | ||
278 | } | ||
279 | |||
280 | DIR* app_opendir(const char *_name) | ||
219 | { | 281 | { |
220 | char realpath[MAX_PATH]; | 282 | char realpath[MAX_PATH]; |
221 | const char *fname = handle_special_dirs(name, 0, realpath, sizeof(realpath)); | 283 | const char *name = handle_special_dirs(_name, 0, realpath, sizeof(realpath)); |
222 | return opendir(fname); | 284 | char *buf = malloc(sizeof(struct __dir) + strlen(name)+1); |
285 | if (!buf) | ||
286 | return NULL; | ||
287 | |||
288 | struct __dir *this = (struct __dir*)buf; | ||
289 | /* definitely fits due to strlen() */ | ||
290 | strcpy(this->path, name); | ||
291 | |||
292 | this->dir = opendir(name); | ||
293 | |||
294 | if (!this->dir) | ||
295 | { | ||
296 | free(buf); | ||
297 | return NULL; | ||
298 | } | ||
299 | return (DIR*)this; | ||
300 | } | ||
301 | |||
302 | int app_closedir(DIR *dir) | ||
303 | { | ||
304 | struct __dir *this = (struct __dir*)dir; | ||
305 | int ret = closedir(this->dir); | ||
306 | free(this); | ||
307 | return ret; | ||
308 | } | ||
309 | |||
310 | |||
311 | struct dirent* app_readdir(DIR* dir) | ||
312 | { | ||
313 | struct __dir *d = (struct __dir*)dir; | ||
314 | return readdir(d->dir); | ||
223 | } | 315 | } |
224 | 316 | ||
317 | |||
225 | int app_mkdir(const char* name) | 318 | int app_mkdir(const char* name) |
226 | { | 319 | { |
227 | char realpath[MAX_PATH]; | 320 | char realpath[MAX_PATH]; |
228 | const char *fname = handle_special_dirs(name, NEED_WRITE, realpath, sizeof(realpath)); | 321 | const char *fname = handle_special_dirs(name, NEED_WRITE, realpath, sizeof(realpath)); |
229 | return mkdir(fname); | 322 | return mkdir(fname, 0777); |
230 | } | 323 | } |
231 | 324 | ||
325 | |||
232 | int app_rmdir(const char* name) | 326 | int app_rmdir(const char* name) |
233 | { | 327 | { |
234 | char realpath[MAX_PATH]; | 328 | char realpath[MAX_PATH]; |
235 | const char *fname = handle_special_dirs(name, NEED_WRITE, realpath, sizeof(realpath)); | 329 | const char *fname = handle_special_dirs(name, NEED_WRITE, realpath, sizeof(realpath)); |
236 | return rmdir(fname); | 330 | return rmdir(fname); |
237 | } | 331 | } |
238 | |||
239 | #else | ||
240 | |||
241 | int app_open(const char *name, int o, ...) | ||
242 | { | ||
243 | if (o & O_CREAT) | ||
244 | { | ||
245 | int ret; | ||
246 | va_list ap; | ||
247 | va_start(ap, o); | ||
248 | ret = open(name, o, va_arg(ap, mode_t)); | ||
249 | va_end(ap); | ||
250 | return ret; | ||
251 | } | ||
252 | return open(name, o); | ||
253 | } | ||
254 | |||
255 | int app_creat(const char* name, mode_t mode) { return creat(name, mode); } | ||
256 | int app_remove(const char *name) { return remove(name); } | ||
257 | int app_rename(const char *old, const char *new) { return rename(old,new); } | ||
258 | DIR *app_opendir(const char *name) { return (DIR*)opendir(name); } /* cast to remove warning in checkwps */ | ||
259 | int app_mkdir(const char* name) { return mkdir(name); } | ||
260 | int app_rmdir(const char* name) { return rmdir(name); } | ||
261 | |||
262 | #endif | ||