summaryrefslogtreecommitdiff
path: root/firmware/common/rbpaths.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/common/rbpaths.c')
-rw-r--r--firmware/common/rbpaths.c49
1 files changed, 35 insertions, 14 deletions
diff --git a/firmware/common/rbpaths.c b/firmware/common/rbpaths.c
index dba39476fc..c59ef7cf65 100644
--- a/firmware/common/rbpaths.c
+++ b/firmware/common/rbpaths.c
@@ -28,6 +28,7 @@
28#include <unistd.h> 28#include <unistd.h>
29#include "config.h" 29#include "config.h"
30#include "rbpaths.h" 30#include "rbpaths.h"
31#include "crc32.h"
31#include "file.h" /* MAX_PATH */ 32#include "file.h" /* MAX_PATH */
32#include "logf.h" 33#include "logf.h"
33#include "gcc_extensions.h" 34#include "gcc_extensions.h"
@@ -52,9 +53,11 @@
52 53
53#if (CONFIG_PLATFORM & PLATFORM_ANDROID) 54#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
54static const char rbhome[] = "/sdcard"; 55static const char rbhome[] = "/sdcard";
55#endif 56#elif (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO|PLATFORM_PANDORA)) && !defined(__PCTOOL__)
56#if (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO|PLATFORM_PANDORA)) && !defined(__PCTOOL__)
57const char *rbhome; 57const char *rbhome;
58#else
59/* YPR0, YPR1 */
60static const char rbhome[] = HOME_DIR;
58#endif 61#endif
59 62
60#if !(defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1)) && !defined(__PCTOOL__) 63#if !(defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1)) && !defined(__PCTOOL__)
@@ -62,9 +65,6 @@ const char *rbhome;
62 * over the ones where Rockbox is installed to. Classic example would be 65 * over the ones where Rockbox is installed to. Classic example would be
63 * $HOME/.config/rockbox.org vs /usr/share/rockbox */ 66 * $HOME/.config/rockbox.org vs /usr/share/rockbox */
64#define HAVE_SPECIAL_DIRS 67#define HAVE_SPECIAL_DIRS
65#define IS_HOME(p) (!strcmp(p, rbhome))
66#else
67#define IS_HOME(p) (!strcmp(p, HOME_DIR))
68#endif 68#endif
69 69
70/* flags for get_user_file_path() */ 70/* flags for get_user_file_path() */
@@ -75,6 +75,7 @@ const char *rbhome;
75#define IS_FILE (1<<1) 75#define IS_FILE (1<<1)
76 76
77#ifdef HAVE_MULTIDRIVE 77#ifdef HAVE_MULTIDRIVE
78static uint32_t rbhome_hash;
78/* A special link is created under e.g. HOME_DIR/<microSD1>, e.g. to access 79/* A special link is created under e.g. HOME_DIR/<microSD1>, e.g. to access
79 * external storage in a convinient location, much similar to the mount 80 * external storage in a convinient location, much similar to the mount
80 * point on our native targets. Here they are treated as symlink (one which 81 * point on our native targets. Here they are treated as symlink (one which
@@ -103,9 +104,9 @@ static const char *handle_special_links(const char* link, unsigned flags,
103} 104}
104#endif 105#endif
105 106
106#ifdef HAVE_SPECIAL_DIRS
107void paths_init(void) 107void paths_init(void)
108{ 108{
109#ifdef HAVE_SPECIAL_DIRS
109 /* make sure $HOME/.config/rockbox.org exists, it's needed for config.cfg */ 110 /* make sure $HOME/.config/rockbox.org exists, it's needed for config.cfg */
110#if (CONFIG_PLATFORM & PLATFORM_ANDROID) 111#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
111 mkdir("/sdcard/rockbox", 0777); 112 mkdir("/sdcard/rockbox", 0777);
@@ -133,9 +134,14 @@ void paths_init(void)
133 snprintf(config_dir, sizeof(config_dir), "%s/.config/rockbox.org/rocks.data", home); 134 snprintf(config_dir, sizeof(config_dir), "%s/.config/rockbox.org/rocks.data", home);
134 mkdir(config_dir, 0777); 135 mkdir(config_dir, 0777);
135#endif 136#endif
137#endif /* HAVE_SPECIAL_DIRS */
136 138
139#ifdef HAVE_MULTIDRIVE
140 rbhome_hash = crc_32((const void *) rbhome, strlen(rbhome), 0xffffffff);
141#endif /* HAVE_MULTIDRIVE */
137} 142}
138 143
144#ifdef HAVE_SPECIAL_DIRS
139static bool try_path(const char* filename, unsigned flags) 145static bool try_path(const char* filename, unsigned flags)
140{ 146{
141 if (flags & IS_FILE) 147 if (flags & IS_FILE)
@@ -189,8 +195,6 @@ static const char* _get_user_file_path(const char *path,
189 return ret; 195 return ret;
190} 196}
191 197
192#elif !defined(paths_init)
193void paths_init(void) { }
194#endif 198#endif
195 199
196static const char* handle_special_dirs(const char* dir, unsigned flags, 200static const char* handle_special_dirs(const char* dir, unsigned flags,
@@ -261,7 +265,14 @@ int app_rename(const char *old, const char *new)
261 * get_dir_info() */ 265 * get_dir_info() */
262struct __dir { 266struct __dir {
263 DIR *dir; 267 DIR *dir;
264 IF_MD(int volumes_returned); 268#ifdef HAVE_MULTIDRIVE
269 int volumes_returned;
270 /* A crc of rbhome is used to speed op the common case where
271 * readdir()/get_dir_info() is called on non-rbhome paths, because
272 * each call needs to check against rbhome for the virtual
273 * mount point of the external storage */
274 uint32_t path_hash;
275#endif
265 char path[]; 276 char path[];
266}; 277};
267 278
@@ -278,7 +289,9 @@ struct dirinfo dir_get_info(DIR* _parent, struct dirent *dir)
278#ifdef HAVE_MULTIDRIVE 289#ifdef HAVE_MULTIDRIVE
279 char vol_string[VOL_ENUM_POS + 8]; 290 char vol_string[VOL_ENUM_POS + 8];
280 sprintf(vol_string, VOL_NAMES, 1); 291 sprintf(vol_string, VOL_NAMES, 1);
281 if (!strcmp(vol_string, dir->d_name)) 292 if (UNLIKELY(rbhome_hash == parent->path_hash) &&
293 /* compare path anyway because of possible hash collision */
294 !strcmp(vol_string, dir->d_name))
282 { 295 {
283 ret.attribute = ATTR_LINK; 296 ret.attribute = ATTR_LINK;
284 strcpy(path, MULTIDRIVE_DIR); 297 strcpy(path, MULTIDRIVE_DIR);
@@ -314,9 +327,11 @@ struct dirinfo dir_get_info(DIR* _parent, struct dirent *dir)
314 327
315DIR* app_opendir(const char *_name) 328DIR* app_opendir(const char *_name)
316{ 329{
330 size_t name_len;
317 char realpath[MAX_PATH]; 331 char realpath[MAX_PATH];
318 const char *name = handle_special_dirs(_name, 0, realpath, sizeof(realpath)); 332 const char *name = handle_special_dirs(_name, 0, realpath, sizeof(realpath));
319 char *buf = malloc(sizeof(struct __dir) + strlen(name)+1); 333 name_len = strlen(name);
334 char *buf = malloc(sizeof(struct __dir) + name_len+1);
320 if (!buf) 335 if (!buf)
321 return NULL; 336 return NULL;
322 337
@@ -331,7 +346,11 @@ DIR* app_opendir(const char *_name)
331 free(buf); 346 free(buf);
332 return NULL; 347 return NULL;
333 } 348 }
334 IF_MD(this->volumes_returned = 0); 349#ifdef HAVE_MULTIDRIVE
350 this->volumes_returned = 0;
351 this->path_hash = crc_32((const void *)this->path, name_len, 0xffffffff);
352#endif
353
335 return (DIR*)this; 354 return (DIR*)this;
336} 355}
337 356
@@ -350,9 +369,11 @@ struct dirent* app_readdir(DIR* dir)
350#ifdef HAVE_MULTIDRIVE 369#ifdef HAVE_MULTIDRIVE
351 /* this is not MT-safe but OK according to man readdir */ 370 /* this is not MT-safe but OK according to man readdir */
352 static struct dirent voldir; 371 static struct dirent voldir;
353 if (d->volumes_returned < (NUM_VOLUMES-1) 372 if (UNLIKELY(rbhome_hash == d->path_hash)
373 && d->volumes_returned < (NUM_VOLUMES-1)
354 && volume_present(d->volumes_returned+1) 374 && volume_present(d->volumes_returned+1)
355 && IS_HOME(d->path)) 375 /* compare path anyway because of possible hash collision */
376 && !strcmp(d->path, rbhome))
356 { 377 {
357 d->volumes_returned += 1; 378 d->volumes_returned += 1;
358 sprintf(voldir.d_name, VOL_NAMES, d->volumes_returned); 379 sprintf(voldir.d_name, VOL_NAMES, d->volumes_returned);