diff --git a/apps/codecs.c b/apps/codecs.c
index 154faa3..29a6644 100644
--- a/apps/codecs.c
+++ b/apps/codecs.c
@@ -193,8 +193,8 @@ struct codec_api ci = {
 
 void codec_get_full_path(char *path, const char *codec_root_fn)
 {
-    snprintf(path, MAX_PATH-1, CODECS_DIR "/%s." CODEC_EXTENSION,
-             codec_root_fn);
+    snprintf(path, MAX_PATH-1, "%s/%s." CODEC_EXTENSION,
+             CODECS_DIR, codec_root_fn);
 }
 
 static int codec_load_ram(int size, struct codec_api *api)
diff --git a/apps/filetree.c b/apps/filetree.c
index 460ab9e..fa942b2 100644
--- a/apps/filetree.c
+++ b/apps/filetree.c
@@ -609,11 +609,12 @@ int ft_enter(struct tree_context* c)
             case FILE_ATTR_ROCK:
             case FILE_ATTR_LUA:
             {
-                char *plugin = buf, *argument = NULL;
+                char *plugin = buf, *argument = NULL, lua_path[MAX_PATH];
                 int ret;
 
                 if ((file->attr & FILE_ATTR_MASK) == FILE_ATTR_LUA) {
-                    plugin = VIEWERS_DIR "/lua.rock"; /* Use a #define here ? */
+                    snprintf(lua_path, sizeof(lua_path)-1, "%s/lua.rock", VIEWERS_DIR); /* Use a #define here ? */
+                    plugin = lua_path;
                     argument = buf;
                 }
 
diff --git a/apps/filetypes.c b/apps/filetypes.c
index 4be2437..67a4c17 100644
--- a/apps/filetypes.c
+++ b/apps/filetypes.c
@@ -175,7 +175,7 @@ static char *filetypes_strdup(char* string)
     return buffer;
 }
 static void read_builtin_types(void);
-static void read_config(char* config_file);
+static void read_config(const char* config_file);
 #ifdef HAVE_LCD_COLOR
 /* Colors file format is similar to icons:
  * ext:hex_color
@@ -272,6 +272,7 @@ void read_viewer_theme_file(void)
 
 void  filetype_init(void)
 {
+    char path[MAX_PATH];
     /* set the directory item first */
     filetypes[0].extension = NULL;
     filetypes[0].plugin = NULL;
@@ -280,7 +281,7 @@ void  filetype_init(void)
     
     filetype_count = 1;
     read_builtin_types();
-    read_config(VIEWERS_CONFIG);
+    read_config(get_user_file_path(VIEWERS_CONFIG, IS_FILE, path, sizeof(path)));
 #ifdef HAVE_LCD_BITMAP
     read_viewer_theme_file();
 #endif
@@ -320,7 +321,7 @@ static void read_builtin_types(void)
     }
 }
 
-static void read_config(char* config_file)
+static void read_config(const char* config_file)
 {
     char line[64], *s, *e;
     char extension[8], plugin[32];
diff --git a/apps/gui/skin_engine/skin_fonts.c b/apps/gui/skin_engine/skin_fonts.c
index f446a99..6b8057c 100644
--- a/apps/gui/skin_engine/skin_fonts.c
+++ b/apps/gui/skin_engine/skin_fonts.c
@@ -100,7 +100,7 @@ int skin_font_load(char* font_name)
     pf->buffer_size = SKIN_FONT_SIZE;
     
     snprintf(filename, MAX_PATH, FONT_DIR "/%s.fnt", font_name);
-    strcpy(font->name, font_name);
+    get_user_file_path(filename, FORCE_BUFFER_COPY, font->name, sizeof(font->name));
     
     pf->fd = -1;
     font->font_id = font_load(pf, filename);
diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c
index a62791e..66baaf2 100644
--- a/apps/gui/skin_engine/skin_parser.c
+++ b/apps/gui/skin_engine/skin_parser.c
@@ -2379,7 +2379,8 @@ bool skin_data_load(enum screen_type screen, struct wps_data *wps_data,
         strlcpy(bmpdir, buf, dot - buf + 1);
     }
     else
-    {
+    {   /* fall back to backdrop dir for built-in themes */
+        /* no get_user_file_path(), assuming we ship bmps for built-in themes */
         snprintf(bmpdir, MAX_PATH, "%s", BACKDROP_DIR);
     }
     /* load the bitmaps that were found by the parsing */
diff --git a/apps/gui/theme_settings.c b/apps/gui/theme_settings.c
index f3628f6..753414e 100644
--- a/apps/gui/theme_settings.c
+++ b/apps/gui/theme_settings.c
@@ -89,7 +89,9 @@ void settings_apply_skins(void)
         CHART2(">skin load ", skins[i].suffix);
         if (skins[i].setting[0] && skins[i].setting[0] != '-')
         {
-            snprintf(buf, sizeof buf, WPS_DIR "/%s.%s",
+            char path[MAX_PATH];
+            snprintf(buf, sizeof buf, "%s/%s.%s",
+                     get_user_file_path(WPS_DIR, false, path, sizeof(path)),
                      skins[i].setting, skins[i].suffix);
             skins[i].loadfunc(screen, buf, true);
         }
diff --git a/apps/main.c b/apps/main.c
index f1f30ce..056604f 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -131,6 +131,9 @@ static void init(void);
 #endif
 int main(int argc, char *argv[])
 {
+#ifdef APPLICATION
+    paths_init();
+#endif
     sys_handle_argv(argc, argv);
 #else
 /* main(), and various functions called by main() and init() may be
@@ -163,11 +166,17 @@ int main(void)
 
 #ifdef AUTOROCK
     {
-        static const char filename[] = PLUGIN_APPS_DIR "/autostart.rock";
-
-        if(file_exists(filename)) /* no complaint if it doesn't exist */
+        char filename[MAX_PATH];
+        const char *file = get_user_file_path(
+#ifdef APPLICATION
+                                ROCKBOX_DIR
+#else
+                                PLUGIN_APPS_DIR
+#endif
+            "/autostart.rock", NEED_WRITE|IS_FILE, filename, sizeof(filename));
+        if(file_exists(file)) /* no complaint if it doesn't exist */
         {
-            plugin_load((char*)filename, NULL); /* start if it does */
+            plugin_load(file, NULL); /* start if it does */
         }
     }
 #endif /* #ifdef AUTOROCK */
diff --git a/apps/menus/main_menu.c b/apps/menus/main_menu.c
index 2a4b344..bb6650c 100644
--- a/apps/menus/main_menu.c
+++ b/apps/menus/main_menu.c
@@ -110,9 +110,12 @@ MAKE_MENU(manage_settings, ID2P(LANG_MANAGE_MENU), NULL, Icon_Config,
 /***********************************/
 /*      INFO MENU                  */
 
+
 static bool show_credits(void)
 {
-    if (plugin_load(VIEWERS_DIR "/credits.rock",NULL) != PLUGIN_OK)
+    char credits[MAX_PATH] = { '\0' };
+    snprintf(credits, MAX_PATH, "%s/credits.rock", VIEWERS_DIR);
+    if (plugin_load(credits, NULL) != PLUGIN_OK)
     {
         /* show the rockbox logo and version untill a button is pressed */
         show_logo();
diff --git a/apps/menus/theme_menu.c b/apps/menus/theme_menu.c
index f8fb06b..c655372 100644
--- a/apps/menus/theme_menu.c
+++ b/apps/menus/theme_menu.c
@@ -241,9 +241,11 @@ static struct browse_folder_info themes = {THEME_DIR, SHOW_CFG};
 
 int browse_folder(void *param)
 {
+    char path[MAX_PATH];
     const struct browse_folder_info *info =
         (const struct browse_folder_info*)param;
-    return rockbox_browse(info->dir, info->show_options);
+    return rockbox_browse(get_user_file_path(info->dir, 0, path, sizeof(path)),
+                          info->show_options);
 }
 
 #ifdef HAVE_LCD_BITMAP
diff --git a/apps/misc.c b/apps/misc.c
index bae8dfb..01f25c1 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -742,35 +742,6 @@ char* strrsplt(char* str, int c)
     return s;
 }
 
-/* Test file existence, using dircache of possible */
-bool file_exists(const char *file)
-{
-    int fd;
-
-    if (!file || strlen(file) <= 0)
-        return false;
-
-#ifdef HAVE_DIRCACHE
-    if (dircache_is_enabled())
-        return (dircache_get_entry_ptr(file) != NULL);
-#endif
-
-    fd = open(file, O_RDONLY);
-    if (fd < 0)
-        return false;
-    close(fd);
-    return true;
-}
-
-bool dir_exists(const char *path)
-{
-    DIR* d = opendir(path);
-    if (!d)
-        return false;
-    closedir(d);
-    return true;
-}
-
 /*
  * removes the extension of filename (if it doesn't start with a .)
  * puts the result in buffer
diff --git a/apps/misc.h b/apps/misc.h
index 34f754b..3ca2091 100644
--- a/apps/misc.h
+++ b/apps/misc.h
@@ -84,8 +84,6 @@ int hex_to_rgb(const char* hex, int* color);
 
 char* strrsplt(char* str, int c);
 char* skip_whitespace(char* const str);
-bool file_exists(const char *file);
-bool dir_exists(const char *path);
 
 /*
  * removes the extension of filename (if it doesn't start with a .)
diff --git a/apps/playlist.c b/apps/playlist.c
index 4a6db88..2896f62 100644
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -86,6 +86,7 @@
 #include "screens.h"
 #include "buffer.h"
 #include "misc.h"
+#include "filefuncs.h"
 #include "button.h"
 #include "filetree.h"
 #include "abrepeat.h"
@@ -103,7 +104,6 @@
 #include "rbunicode.h"
 #include "root_menu.h"
 
-#define PLAYLIST_CONTROL_FILE ROCKBOX_DIR "/.playlist_control"
 #define PLAYLIST_CONTROL_FILE_VERSION 2
 
 /*
@@ -1440,7 +1440,12 @@ static int get_next_dir(char *dir, bool is_forward, bool recursion)
     /* process random folder advance */
     if (global_settings.next_folder == FOLDER_ADVANCE_RANDOM)
     {
-        int fd = open(ROCKBOX_DIR "/folder_advance_list.dat", O_RDONLY);
+        char folder_advance_list[MAX_PATH];
+        get_user_file_path(ROCKBOX_DIR, FORCE_BUFFER_COPY,
+                folder_advance_list, sizeof(folder_advance_list));
+        strlcat(folder_advance_list, "/folder_advance_list.dat",
+                sizeof(folder_advance_list));
+        int fd = open(folder_advance_list, O_RDONLY);
         if (fd >= 0)
         {
             char buffer[MAX_PATH];
@@ -1910,7 +1915,8 @@ void playlist_init(void)
     struct playlist_info* playlist = &current_playlist;
 
     playlist->current = true;
-    strlcpy(playlist->control_filename, PLAYLIST_CONTROL_FILE,
+    get_user_file_path(PLAYLIST_CONTROL_FILE, IS_FILE|NEED_WRITE|FORCE_BUFFER_COPY,
+            playlist->control_filename,
             sizeof(playlist->control_filename));
     playlist->fd = -1;
     playlist->control_fd = -1;
diff --git a/apps/playlist_catalog.c b/apps/playlist_catalog.c
index f9a43da..2fbffda 100644
--- a/apps/playlist_catalog.c
+++ b/apps/playlist_catalog.c
@@ -32,6 +32,7 @@
 #include "lang.h"
 #include "list.h"
 #include "misc.h"
+#include "filefuncs.h"
 #include "onplay.h"
 #include "playlist.h"
 #include "settings.h"
@@ -77,8 +78,13 @@ static int initialize_catalog(void)
 
         /* fall back to default directory if no or invalid config */
         if (default_dir)
-            strlcpy(playlist_dir, PLAYLIST_CATALOG_DEFAULT_DIR,
-                sizeof(playlist_dir));
+        {
+            const char *dir = get_user_file_path(PLAYLIST_CATALOG_DEFAULT_DIR,
+                                    FORCE_BUFFER_COPY|NEED_WRITE,
+                                    playlist_dir, sizeof(playlist_dir));
+            if (!dir_exists(dir))
+                mkdir(dir);
+        }
 
         playlist_dir_length = strlen(playlist_dir);
 
diff --git a/apps/plugin.c b/apps/plugin.c
index 81ba006..b3baea7 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -41,6 +41,7 @@
 #include "pcmbuf.h"
 #include "errno.h"
 #include "diacritic.h"
+#include "filefuncs.h"
 
 #if CONFIG_CHARGING
 #include "power.h"
diff --git a/apps/plugin.h b/apps/plugin.h
index cf1fd77..5ee18d0 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -66,6 +66,7 @@ void* plugin_get_buffer(size_t *buffer_size);
 #include "profile.h"
 #endif
 #include "misc.h"
+#include "filefuncs.h"
 #if (CONFIG_CODEC == SWCODEC)
 #include "dsp.h"
 #include "codecs.h"
diff --git a/apps/radio/presets.c b/apps/radio/presets.c
index aa265bc..e900afe 100644
--- a/apps/radio/presets.c
+++ b/apps/radio/presets.c
@@ -30,6 +30,7 @@
 #include "file.h"
 #include "string-extra.h"
 #include "misc.h"
+#include "filefuncs.h"
 #include "lang.h"
 #include "action.h"
 #include "list.h"
diff --git a/apps/radio/radioart.c b/apps/radio/radioart.c
index 7ba9881..85397c1 100644
--- a/apps/radio/radioart.c
+++ b/apps/radio/radioart.c
@@ -30,6 +30,7 @@
 #include "kernel.h"
 #include "string-extra.h"
 #include "misc.h"
+#include "filefuncs.h"
 
 #define MAX_RADIOART_IMAGES 10
 struct radioart {
diff --git a/apps/recorder/albumart.c b/apps/recorder/albumart.c
index 5eca713..6b43576 100644
--- a/apps/recorder/albumart.c
+++ b/apps/recorder/albumart.c
@@ -26,6 +26,7 @@
 #include "buffering.h"
 #include "dircache.h"
 #include "misc.h"
+#include "filefuncs.h"
 #include "settings.h"
 #include "wps.h"
 
diff --git a/apps/recorder/recording.c b/apps/recorder/recording.c
index ab7e7c9..0098d6b 100644
--- a/apps/recorder/recording.c
+++ b/apps/recorder/recording.c
@@ -56,7 +56,7 @@
 #include "sound_menu.h"
 #include "timefuncs.h"
 #include "debug.h"
-#include "misc.h"
+#include "filefuncs.h"
 #include "tree.h"
 #include "string.h"
 #include "dir.h"
diff --git a/apps/root_menu.c b/apps/root_menu.c
index 53c522a..7965673 100644
--- a/apps/root_menu.c
+++ b/apps/root_menu.c
@@ -341,7 +341,7 @@ static int plugins_menu(void* param)
     MENUITEM_STRINGLIST(plugins_menu_items, ID2P(LANG_PLUGINS), NULL,
                         ID2P(LANG_PLUGIN_GAMES),
                         ID2P(LANG_PLUGIN_APPS), ID2P(LANG_PLUGIN_DEMOS));
-    char *folder;
+    const char *folder;
     int retval = GO_TO_PREVIOUS;
     int selection = 0, current = 0;
     while (retval == GO_TO_PREVIOUS)
@@ -646,7 +646,13 @@ void root_menu(void)
                     if ( action_userabort(HZ/5) ) 
                         break;
                 }
-                next_screen = load_plugin_screen(PLUGIN_DEMOS_DIR "/pictureflow.rock");
+                {
+                    char pf_path[MAX_PATH];
+                    snprintf(pf_path, sizeof(pf_path),
+                            "%s/pictureflow.rock",
+                            PLUGIN_DEMOS_DIR);
+                    next_screen = load_plugin_screen(pf_path);
+                }
                 previous_browser = GO_TO_PICTUREFLOW;
                 break;
 #endif                
diff --git a/apps/scrobbler.c b/apps/scrobbler.c
index 8d9f694..9b0decf 100644
--- a/apps/scrobbler.c
+++ b/apps/scrobbler.c
@@ -33,7 +33,7 @@ http://www.audioscrobbler.net/wiki/Portable_Player_Logging
 #include "buffer.h"
 #include "settings.h"
 #include "ata_idle_notify.h"
-#include "misc.h"
+#include "filefuncs.h"
 #include "appevents.h"
 
 #if CONFIG_RTC
diff --git a/apps/settings.c b/apps/settings.c
index 6f1fd7a..9549d77 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -25,6 +25,7 @@
 #include <limits.h>
 #include "inttypes.h"
 #include "config.h"
+#include "paths.h"
 #include "action.h"
 #include "crc32.h"
 #include "sound.h"
@@ -110,7 +111,6 @@ long lasttime = 0;
 [8-NVRAM_BLOCK_SIZE] data
 */
 #define NVRAM_DATA_START 8
-#define NVRAM_FILE ROCKBOX_DIR "/nvram.bin"
 static char nvram_buffer[NVRAM_BLOCK_SIZE];
 
 static bool read_nvram_data(char* buf, int max_len)
@@ -118,7 +118,9 @@ static bool read_nvram_data(char* buf, int max_len)
     unsigned crc32 = 0xffffffff;
     int var_count = 0, i = 0, buf_pos = 0;
 #ifndef HAVE_RTC_RAM
-    int fd = open(NVRAM_FILE,O_RDONLY);
+    char path[MAX_PATH];
+    int fd = open(get_user_file_path(NVRAM_FILE, IS_FILE|NEED_WRITE,
+                  path, sizeof(path)), O_RDONLY);
     int bytes;
     if (fd < 0)
         return false;
@@ -172,6 +174,7 @@ static bool write_nvram_data(char* buf, int max_len)
     char var_count = 0;
 #ifndef HAVE_RTC_RAM
     int fd;
+    char path[MAX_PATH];
 #endif
     memset(buf,0,max_len);
     /* magic, version */
@@ -195,7 +198,8 @@ static bool write_nvram_data(char* buf, int max_len)
                     max_len-NVRAM_DATA_START-1,0xffffffff);
     memcpy(&buf[4],&crc32,4);
 #ifndef HAVE_RTC_RAM
-    fd = open(NVRAM_FILE,O_CREAT|O_TRUNC|O_WRONLY, 0666);
+    fd = open(get_user_file_path(NVRAM_FILE, IS_FILE|NEED_WRITE,
+                  path, sizeof(path)),O_CREAT|O_TRUNC|O_WRONLY, 0666);
     if (fd >= 0)
     {
         int len = write(fd,buf,max_len);
@@ -226,8 +230,12 @@ void settings_load(int which)
         read_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
     if (which&SETTINGS_HD)
     {
-        settings_load_config(CONFIGFILE,false);
-        settings_load_config(FIXEDSETTINGSFILE,false);
+        const char *file;
+        char path[MAX_PATH];
+        file = get_user_file_path(CONFIGFILE, IS_FILE|NEED_WRITE, path, sizeof(path));
+        settings_load_config(file, false);
+        file = get_user_file_path(FIXEDSETTINGSFILE, IS_FILE, path, sizeof(path));
+        settings_load_config(file, false);
     }
 }
 
@@ -334,10 +342,12 @@ bool settings_load_config(const char* file, bool apply)
                         char storage[MAX_PATH];
                         if (settings[i].filename_setting->prefix)
                         {
-                            int len = strlen(settings[i].filename_setting->prefix);
-                            if (!strncasecmp(value,
-                                             settings[i].filename_setting->prefix,
-                                             len))
+                            char prefix_dir[MAX_PATH];
+                            const char *dir = get_user_file_path(
+                                    settings[i].filename_setting->prefix,
+                                    0, prefix_dir, sizeof(prefix_dir));
+                            int len = strlen(dir);
+                            if (!strncasecmp(value, dir, len))
                             {
                                 strlcpy(storage, &value[len], MAX_PATH);
                             }
@@ -470,6 +480,10 @@ bool cfg_to_string(int i/*setting_id*/, char* buf, int buf_len)
             if (((char*)settings[i].setting)[0]
                 && settings[i].filename_setting->prefix)
             {
+                char path[MAX_PATH];
+                const char *prefix = get_user_file_path(
+                        settings[i].filename_setting->prefix, 0,
+                        path, sizeof(path));
                 if (((char*)settings[i].setting)[0] == '-')
                 {
                     buf[0] = '-';
@@ -477,8 +491,7 @@ bool cfg_to_string(int i/*setting_id*/, char* buf, int buf_len)
                 }
                 else
                 {
-                    snprintf(buf,buf_len,"%s%s%s",
-                            settings[i].filename_setting->prefix,
+                    snprintf(buf,buf_len,"%s%s%s", prefix,
                             (char*)settings[i].setting,
                             settings[i].filename_setting->suffix);
                 }
@@ -589,8 +602,11 @@ static void flush_global_status_callback(void *data)
 static void flush_config_block_callback(void *data)
 {
     (void)data;
+    char path[MAX_PATH];
     write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
-    settings_write_config(CONFIGFILE, SETTINGS_SAVE_CHANGED);
+    settings_write_config(
+            get_user_file_path(CONFIGFILE, IS_FILE|NEED_WRITE, path, sizeof(path)),
+            SETTINGS_SAVE_CHANGED);
 }
 
 /*
@@ -634,8 +650,8 @@ int settings_save(void)
 
 bool settings_save_config(int options)
 {
-    char filename[MAX_PATH];
-    char *folder, *namebase;
+    char filename[MAX_PATH], path[MAX_PATH];
+    const char *folder, *namebase;
     switch (options)
     {
         case SETTINGS_SAVE_THEME:
@@ -663,6 +679,8 @@ bool settings_save_config(int options)
             namebase = "config";
             break;
     }
+
+    folder = get_user_file_path(folder, NEED_WRITE, path, sizeof(path));
     create_numbered_filename(filename, folder, namebase, ".cfg", 2
                              IF_CNFN_NUM_(, NULL));
 
@@ -1180,6 +1198,7 @@ bool set_option(const char* string, const void* variable, enum optiontype type,
     if (!option_screen(&item, NULL, false, NULL))
     {
         if (type == BOOL)
+
             *(bool*)variable = (temp == 1);
         else
             *(int*)variable = temp;
diff --git a/apps/settings.h b/apps/settings.h
index 1cf43d9..1eb00ac 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -33,6 +33,7 @@
 #if CONFIG_CODEC == SWCODEC
 #include "audio.h"
 #endif
+#include "paths.h"
 
 struct opt_items {
     unsigned const char* string;
@@ -40,50 +41,6 @@ struct opt_items {
 };
 
 /** Setting values defines **/
-
-/* name of directory where configuration, fonts and other data
- * files are stored */
-#ifdef __PCTOOL__
-#undef ROCKBOX_DIR
-#undef ROCKBOX_DIR_LEN
-#undef WPS_DIR
-#define ROCKBOX_DIR "."
-#define ROCKBOX_DIR_LEN 1
-#else
-
-/* ROCKBOX_DIR is now defined in autoconf.h for flexible build types */
-#ifndef ROCKBOX_DIR
-#error ROCKBOX_DIR not defined (should be in autoconf.h)
-#endif
-#define ROCKBOX_DIR_LEN (sizeof(ROCKBOX_DIR)-1)
-#endif /* def __PCTOOL__ */
-
-
-#define FONT_DIR    ROCKBOX_DIR "/fonts"
-#define LANG_DIR    ROCKBOX_DIR "/langs"
-#define WPS_DIR     ROCKBOX_DIR "/wps"
-#define SBS_DIR     WPS_DIR
-#define THEME_DIR   ROCKBOX_DIR "/themes"
-#define ICON_DIR    ROCKBOX_DIR "/icons"
-
-#define PLUGIN_DIR          ROCKBOX_DIR "/rocks"
-#define PLUGIN_GAMES_DIR    PLUGIN_DIR "/games"
-#define PLUGIN_APPS_DIR     PLUGIN_DIR "/apps"
-#define PLUGIN_DEMOS_DIR    PLUGIN_DIR "/demos"
-#define VIEWERS_DIR         PLUGIN_DIR "/viewers"
-
-#define BACKDROP_DIR ROCKBOX_DIR "/backdrops"
-#define REC_BASE_DIR "/"
-#define EQS_DIR     ROCKBOX_DIR "/eqs"
-#define CODECS_DIR  ROCKBOX_DIR "/codecs"
-#define RECPRESETS_DIR  ROCKBOX_DIR "/recpresets"
-#define FMPRESET_PATH ROCKBOX_DIR "/fmpresets"
-#define PLAYLIST_CATALOG_DEFAULT_DIR "/Playlists"
-
-#define VIEWERS_CONFIG      ROCKBOX_DIR "/viewers.config"
-#define CONFIGFILE          ROCKBOX_DIR "/config.cfg"
-#define FIXEDSETTINGSFILE   ROCKBOX_DIR "/fixed.cfg"
-
 #define MAX_FILENAME 32
 
 
diff --git a/apps/tagcache.c b/apps/tagcache.c
index 1094c92..898263e 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -73,6 +73,7 @@
 #include "buffer.h"
 #include "crc32.h"
 #include "misc.h"
+#include "filefuncs.h"
 #include "settings.h"
 #include "dir.h"
 #include "structec.h"
@@ -292,15 +293,17 @@ static bool is_dircache_intact(void)
 static int open_tag_fd(struct tagcache_header *hdr, int tag, bool write)
 {
     int fd;
-    char buf[MAX_PATH];
+    char buf[MAX_PATH], path[MAX_PATH];
+    const char * file;
     int rc;
     
     if (TAGCACHE_IS_NUMERIC(tag) || tag < 0 || tag >= TAG_COUNT)
         return -1;
     
     snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, tag);
+    file = get_user_file_path(buf, IS_FILE | NEED_WRITE, path, sizeof(path));
     
-    fd = open(buf, write ? O_RDWR : O_RDONLY);
+    fd = open(file, write ? O_RDWR : O_RDONLY);
     if (fd < 0)
     {
         logf("tag file open failed: tag=%d write=%d file=%s", tag, write, buf);
@@ -325,8 +328,12 @@ static int open_master_fd(struct master_header *hdr, bool write)
 {
     int fd;
     int rc;
+    char path[MAX_PATH];
     
-    fd = open(TAGCACHE_FILE_MASTER, write ? O_RDWR : O_RDONLY);
+    fd = open(get_user_file_path(TAGCACHE_FILE_MASTER,
+                                 IS_FILE|NEED_WRITE,
+                                 path, sizeof(path)),
+                    write ? O_RDWR : O_RDONLY);
     if (fd < 0)
     {
         logf("master file open failed for R/W");
@@ -668,9 +675,11 @@ static bool open_files(struct tagcache_search *tcs, int tag)
 {
     if (tcs->idxfd[tag] < 0)
     {
-        char fn[MAX_PATH];
+        char fn[MAX_PATH], path[MAX_PATH];
+        const char *file;
 
         snprintf(fn, sizeof fn, TAGCACHE_FILE_INDEX, tag);
+        file = get_user_file_path(fn, IS_FILE | NEED_WRITE, path, sizeof(path));
         tcs->idxfd[tag] = open(fn, O_RDONLY);
     }
     
@@ -1159,14 +1168,17 @@ static void remove_files(void)
     tc_stat.ready = false;
     tc_stat.ramcache = false;
     tc_stat.econ = false;
-    remove(TAGCACHE_FILE_MASTER);
+    remove(get_user_file_path(TAGCACHE_FILE_MASTER, NEED_WRITE|IS_FILE,
+                              buf, sizeof(buf)));
     for (i = 0; i < TAG_COUNT; i++)
     {
+        char buf2[MAX_PATH];
         if (TAGCACHE_IS_NUMERIC(i))
             continue;
-        
+
+        /* database_%d.tcd -> database_0.tcd */
         snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, i);
-        remove(buf);
+        remove(get_user_file_path(buf, NEED_WRITE | IS_FILE, buf2, sizeof(buf2)));
     }
 }
 
@@ -1317,10 +1329,11 @@ bool tagcache_search_add_clause(struct tagcache_search *tcs,
     
     if (!TAGCACHE_IS_NUMERIC(clause->tag) && tcs->idxfd[clause->tag] < 0)
     {
-        char buf[MAX_PATH];
-
-        snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, clause->tag);        
-        tcs->idxfd[clause->tag] = open(buf, O_RDONLY);
+        char buf[MAX_PATH], path[MAX_PATH];
+        const char *file;
+        snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, clause->tag);
+        file = get_user_file_path(buf, IS_FILE | NEED_WRITE, path, sizeof(path));
+        tcs->idxfd[clause->tag] = open(file, O_RDONLY);
     }
     
     tcs->clause[tcs->clause_count] = clause;
@@ -2344,7 +2357,8 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
     struct master_header   tcmh;
     struct index_entry idxbuf[IDX_BUF_DEPTH];
     int idxbuf_pos;
-    char buf[TAG_MAXLEN+32];
+    char buf[TAG_MAXLEN+32], path[MAX_PATH];
+    const char *file;
     int fd = -1, masterfd;
     bool error = false;
     int init;
@@ -2492,7 +2506,8 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
          * anything whether the index type is sorted or not.
          */
         snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, index_type);
-        fd = open(buf, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+        file = get_user_file_path(buf, IS_FILE | NEED_WRITE, path, sizeof(path));
+        fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
         if (fd < 0)
         {
             logf("%s open fail", buf);
@@ -2512,18 +2527,21 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
         }
     }
 
+    file = get_user_file_path(TAGCACHE_FILE_MASTER,
+                                            IS_FILE|NEED_WRITE,
+                                            buf, sizeof(buf));
     /* Loading the tag lookup file as "master file". */
     logf("Loading index file");
-    masterfd = open(TAGCACHE_FILE_MASTER, O_RDWR);
+    masterfd = open(file, O_RDWR);
 
     if (masterfd < 0)
     {
         logf("Creating new DB");
-        masterfd = open(TAGCACHE_FILE_MASTER, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+        masterfd = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
 
         if (masterfd < 0)
         {
-            logf("Failure to create index file (%s)", TAGCACHE_FILE_MASTER);
+            logf("Failure to create index file (%s)", file);
             close(fd);
             return -2;
         }
@@ -2831,6 +2849,8 @@ static bool commit(void)
 {
     struct tagcache_header tch;
     struct master_header   tcmh;
+    char path[MAX_PATH];
+    const char *file;
     int i, len, rc;
     int tmpfd;
     int masterfd;
@@ -2844,7 +2864,10 @@ static bool commit(void)
     while (write_lock)
         sleep(1);
 
-    tmpfd = open(TAGCACHE_FILE_TEMP, O_RDONLY);
+    file = get_user_file_path(TAGCACHE_FILE_TEMP,
+                            IS_FILE|NEED_WRITE, path, sizeof(path));
+
+    tmpfd = open(file, O_RDONLY);
     if (tmpfd < 0)
     {
         logf("nothing to commit");
@@ -2860,7 +2883,7 @@ static bool commit(void)
     {
         logf("incorrect tmpheader");
         close(tmpfd);
-        remove(TAGCACHE_FILE_TEMP);
+        remove(file);
         return false;
     }
 
@@ -2868,7 +2891,7 @@ static bool commit(void)
     {
         logf("nothing to commit");
         close(tmpfd);
-        remove(TAGCACHE_FILE_TEMP);
+        remove(file);
         return true;
     }
 
@@ -2876,7 +2899,8 @@ static bool commit(void)
     tc_stat.ready = check_all_headers();
     
 #ifdef HAVE_EEPROM_SETTINGS
-    remove(TAGCACHE_STATEFILE);
+    remove(get_user_file_path(TAGCACHE_STATEFILE, IS_FILE | NEED_WRITE,
+                path, sizeof(path)));
 #endif
     
     /* At first be sure to unload the ramcache! */
@@ -2966,7 +2990,7 @@ static bool commit(void)
     }
     
     close(tmpfd);
-    remove(TAGCACHE_FILE_TEMP);
+    remove(file);
     
     tc_stat.commit_step = 0;
     
@@ -3386,15 +3410,18 @@ bool tagcache_import_changelog(void)
     struct tagcache_header tch;
     int clfd;
     long masterfd;
-    char buf[2048];
+    char buf[MAX(MAX_PATH, 2048)];
+    const char *file;
     
     if (!tc_stat.ready)
         return false;
     
     while (read_lock)
         sleep(1);
-    
-    clfd = open(TAGCACHE_FILE_CHANGELOG, O_RDONLY);
+
+    file = get_user_file_path(TAGCACHE_FILE_CHANGELOG,
+                                   IS_FILE|NEED_WRITE, buf, sizeof(buf));
+    clfd = open(file, O_RDONLY);
     if (clfd < 0)
     {
         logf("failure to open changelog");
@@ -3436,7 +3463,8 @@ bool tagcache_create_changelog(struct tagcache_search *tcs)
 {
     struct master_header myhdr;
     struct index_entry idx;
-    char buf[TAG_MAXLEN+32];
+    const char *file;
+    char buf[MAX(TAG_MAXLEN+32, MAX_PATH)];
     char temp[32];
     int clfd;
     int i, j;
@@ -3448,7 +3476,9 @@ bool tagcache_create_changelog(struct tagcache_search *tcs)
         return false;
     
     /* Initialize the changelog */
-    clfd = open(TAGCACHE_FILE_CHANGELOG, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+    file = get_user_file_path(TAGCACHE_FILE_CHANGELOG, IS_FILE | NEED_WRITE,
+                              buf, sizeof(buf));
+    clfd = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
     if (clfd < 0)
     {
         logf("failure to open changelog");
@@ -3766,11 +3796,15 @@ static bool allocate_tagcache(void)
 static bool tagcache_dumpload(void)
 {
     struct statefile_header shdr;
+    char path[MAX_PATH];
+    const char *file;
     int fd, rc;
     long offpos;
     int i;
-    
-    fd = open(TAGCACHE_STATEFILE, O_RDONLY);
+
+    file = get_user_file_path(TAGCACHE_STATEFILE, IS_FILE | NEED_WRITE,
+                                    path, sizeof(path));
+    fd = open(file, O_RDONLY);
     if (fd < 0)
     {
         logf("no tagcache statedump");
@@ -3816,12 +3850,16 @@ static bool tagcache_dumpload(void)
 static bool tagcache_dumpsave(void)
 {
     struct statefile_header shdr;
+    char path[MAX_PATH];
+    const char *file;
     int fd;
     
     if (!tc_stat.ramcache)
         return false;
     
-    fd = open(TAGCACHE_STATEFILE, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+    file = get_user_file_path(TAGCACHE_STATEFILE, IS_FILE | NEED_WRITE,
+                                    path, sizeof(path));
+    fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
     if (fd < 0)
     {
         logf("failed to create a statedump");
@@ -3847,7 +3885,8 @@ static bool load_tagcache(void)
     long bytesleft = tc_stat.ramcache_allocated;
     struct index_entry *idx;
     int rc, fd;
-    char *p;
+    char *p, path[MAX_PATH];
+    const char *file;
     int i, tag;
 
 # ifdef HAVE_DIRCACHE
@@ -3858,8 +3897,11 @@ static bool load_tagcache(void)
 # endif
     
     logf("loading tagcache to ram...");
-    
-    fd = open(TAGCACHE_FILE_MASTER, O_RDONLY);
+
+    file = get_user_file_path(TAGCACHE_FILE_MASTER,
+                              IS_FILE|NEED_WRITE,
+                              path, sizeof(path));
+    fd = open(file, O_RDONLY);
     if (fd < 0)
     {
         logf("tagcache open failed");
@@ -4069,12 +4111,14 @@ static bool load_tagcache(void)
 static bool check_deleted_files(void)
 {
     int fd;
-    char buf[TAG_MAXLEN+32];
+    char buf[TAG_MAXLEN+32], path[MAX_PATH];
+    const char *file;
     struct tagfile_entry tfe;
     
     logf("reverse scan...");
     snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, tag_filename);
-    fd = open(buf, O_RDONLY);
+    file = get_user_file_path(buf, IS_FILE | NEED_WRITE, path, sizeof(path));
+    fd = open(file, O_RDONLY);
     
     if (fd < 0)
     {
@@ -4232,6 +4276,8 @@ void tagcache_build(const char *path)
 {
     struct tagcache_header header;
     bool ret;
+    char buf[MAX_PATH];
+    const char *file;
 
     curpath[0] = '\0';
     data_size = 0;
@@ -4244,19 +4290,21 @@ void tagcache_build(const char *path)
 #endif
     
     logf("updating tagcache");
+
+    file = get_user_file_path(TAGCACHE_FILE_TEMP,
+                                    IS_FILE|NEED_WRITE, buf, sizeof(buf));
     
-    cachefd = open(TAGCACHE_FILE_TEMP, O_RDONLY);
-    if (cachefd >= 0)
+
+    if (file_exists(file))
     {
         logf("skipping, cache already waiting for commit");
-        close(cachefd);
         return ;
     }
     
-    cachefd = open(TAGCACHE_FILE_TEMP, O_RDWR | O_CREAT | O_TRUNC, 0666);
+    cachefd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0666);
     if (cachefd < 0)
     {
-        logf("master file open failed: %s", TAGCACHE_FILE_TEMP);
+        logf("master file open failed: %s", file);
         return ;
     }
 
@@ -4300,7 +4348,7 @@ void tagcache_build(const char *path)
 #endif
     if (commit())
     {
-        remove(TAGCACHE_FILE_TEMP);
+        remove(file);
         logf("tagcache built!");
     }
 #ifdef __PCTOOL__
@@ -4345,7 +4393,12 @@ void tagcache_unload_ramcache(void)
 {
     tc_stat.ramcache = false;
     /* Just to make sure there is no statefile present. */
-    // remove(TAGCACHE_STATEFILE);
+
+#if 0
+    char path[MAX_PATH];
+    remove(get_user_file_path(TAGCACHE_STATEFILE, IS_FILE | NEED_WRITE,
+                path, sizeof(path)));
+#endif
 }
 #endif
 
@@ -4354,6 +4407,7 @@ static void tagcache_thread(void)
 {
     struct queue_event ev;
     bool check_done = false;
+    char path[MAX_PATH];
 
     /* If the previous cache build/update was interrupted, commit
      * the changes first in foreground. */
@@ -4370,7 +4424,8 @@ static void tagcache_thread(void)
         check_done = tagcache_dumpload();
     }
 
-    remove(TAGCACHE_STATEFILE);
+    remove(get_user_file_path(TAGCACHE_STATEFILE, IS_FILE | NEED_WRITE,
+                buf, sizeof(buf)));
 # endif
     
     /* Allocate space for the tagcache if found on disk. */
@@ -4403,7 +4458,8 @@ static void tagcache_thread(void)
             
             case Q_REBUILD:
                 remove_files();
-                remove(TAGCACHE_FILE_TEMP);
+                remove(get_user_file_path(TAGCACHE_FILE_TEMP,
+                                IS_FILE|NEED_WRITE, path, sizeof(path)));
                 tagcache_build("/");
                 break;
             
diff --git a/apps/tree.c b/apps/tree.c
index d63ddd4..ed8e4d2 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -52,6 +52,7 @@
 #include "talk.h"
 #include "filetypes.h"
 #include "misc.h"
+#include "filefuncs.h"
 #include "filetree.h"
 #include "tagtree.h"
 #ifdef HAVE_RECORDING
@@ -260,7 +261,8 @@ static int tree_voice_cb(int selected_item, void * data)
 
 bool check_rockboxdir(void)
 {
-    if(!dir_exists(ROCKBOX_DIR))
+    char path[MAX_PATH];
+    if(!dir_exists(get_user_file_path(ROCKBOX_DIR, 0, path, sizeof(path))))
     {   /* No need to localise this message.
            If .rockbox is missing, it wouldn't work anyway */
         int i;
diff --git a/firmware/SOURCES b/firmware/SOURCES
index b4f5301..b643a68 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -105,6 +105,9 @@ common/dircache.c
 #endif /* HAVE_DIRCACHE */
 common/filefuncs.c
 common/format.c
+#ifdef APPLICATION
+common/paths.c
+#endif
 common/strcasecmp.c
 common/strcasestr.c
 common/strnatcmp.c
diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c
index 906527f..7b2cdd1 100644
--- a/firmware/common/dircache.c
+++ b/firmware/common/dircache.c
@@ -88,10 +88,13 @@ static int fdbind_idx = 0;
  */
 static int open_dircache_file(unsigned flags, int permissions)
 {
+    char path[MAX_PATH];
+    const char *file = get_user_file_path(DIRCACHE_FILE, IS_FILE|NEED_WRITE,
+                                path, sizeof(path));
     if (permissions != 0)
-        return open(DIRCACHE_FILE, flags, permissions);
+        return open(file, flags, permissions);
 
-    return open(DIRCACHE_FILE, flags);
+    return open(file, flags);
 }
 
 /**
@@ -99,7 +102,9 @@ static int open_dircache_file(unsigned flags, int permissions)
  */
 static int remove_dircache_file(void)
 {
-    return remove(DIRCACHE_FILE);
+    char path[MAX_PATH];
+    return remove(get_user_file_path(DIRCACHE_FILE, IS_FILE|NEED_WRITE,
+                                path, sizeof(path)));
 }
 #endif
 /** 
diff --git a/firmware/common/filefuncs.c b/firmware/common/filefuncs.c
index ca91132..c058267 100644
--- a/firmware/common/filefuncs.c
+++ b/firmware/common/filefuncs.c
@@ -22,6 +22,7 @@
 #include "dir.h"
 #include "stdlib.h"
 #include "string.h"
+#include "debug.h"
 
 #ifdef HAVE_MULTIVOLUME
 /* returns on which volume this is, and copies the reduced name
@@ -50,3 +51,39 @@ int strip_volume(const char* name, char* namecopy)
     return volume;
 }
 #endif /* #ifdef HAVE_MULTIVOLUME */
+
+#ifndef __PCTOOL__
+/* Test file existence, using dircache of possible */
+bool file_exists(const char *file)
+{
+    int fd;
+
+#ifdef DEBUG
+    if (!file || strlen(file) <= 0)
+    {
+        DEBUGF("%s(): Invalid parameter!\n");
+        return false;
+    }
+#endif
+
+#ifdef HAVE_DIRCACHE
+    if (dircache_is_enabled())
+        return (dircache_get_entry_ptr(file) != NULL);
+#endif
+
+    fd = open(file, O_RDONLY);
+    if (fd < 0)
+        return false;
+    close(fd);
+    return true;
+}
+
+bool dir_exists(const char *path)
+{
+    DIR* d = opendir(path);
+    if (!d)
+        return false;
+    closedir(d);
+    return true;
+}
+#endif /* __PCTOOL__ */
diff --git a/firmware/common/paths.c b/firmware/common/paths.c
new file mode 100644
index 0000000..1adff3c
--- /dev/null
+++ b/firmware/common/paths.c
@@ -0,0 +1,84 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+
+#include <stdio.h> /* snprintf */
+#include <stdlib.h>
+#include "paths.h"
+#include "file.h" /* MAX_PATH */
+#include "dir.h"
+#include "gcc_extensions.h"
+#include "string-extra.h"
+#include "filefuncs.h"
+
+
+void paths_init(void)
+{
+    /* make sure $HOME/.config/rockbox.org exists, it's needed for config.cfg */
+    char home_path[MAX_PATH];
+    snprintf(home_path, sizeof(home_path), "%s/.config/rockbox.org", getenv("HOME"));
+    mkdir(home_path);
+}
+
+const char* get_user_file_path(const char *path,
+                               unsigned flags,
+                               char* buf,
+                               const size_t bufsize)
+{
+    const char *ret = path;
+    const char *pos = path;
+    printf("%s(): looking for %s\n", __func__, path);
+    /* replace ROCKBOX_DIR in path with $HOME/.config/rockbox.org */
+    pos += ROCKBOX_DIR_LEN;
+    if (*pos == '/') pos += 1;
+
+    if (snprintf(buf, bufsize, "%s/.config/rockbox.org/%s", getenv("HOME"), pos)
+            >= (int)bufsize)
+        return NULL;
+
+    /* always return the replacement buffer (pointing to $HOME) if
+     * write access is needed */
+    if (flags & NEED_WRITE)
+        ret = buf;
+    else
+    {
+        if (flags & IS_FILE)
+        {
+            if (file_exists(buf))
+                ret = buf;
+        }
+        else
+        {
+            if (dir_exists(buf))
+                ret = buf;
+        }
+    }
+
+    /* make a copy if we're about to return the path*/
+    if (UNLIKELY((flags & FORCE_BUFFER_COPY) && (ret != buf)))
+    {
+        strlcpy(buf, ret, bufsize);
+        ret = buf;
+    }
+
+    printf("%s(): %s\n", __func__, ret);
+    return ret;
+}
diff --git a/firmware/common/unicode.c b/firmware/common/unicode.c
index 4ef6eaa..6844c82 100644
--- a/firmware/common/unicode.c
+++ b/firmware/common/unicode.c
@@ -27,16 +27,16 @@
  */
 
 #include <stdio.h>
+#include "config.h"
 #include "file.h"
 #include "debug.h"
 #include "rbunicode.h"
-#include "config.h"
+#include "paths.h"
 
 #ifndef O_BINARY
 #define O_BINARY 0
 #endif
 
-#define CODEPAGE_DIR    ROCKBOX_DIR"/codepages"
 static int default_codepage = 0;
 static int loaded_cp_table = 0;
 
diff --git a/firmware/export/filefuncs.h b/firmware/export/filefuncs.h
index 130c5ff..3745c6b 100644
--- a/firmware/export/filefuncs.h
+++ b/firmware/export/filefuncs.h
@@ -28,4 +28,9 @@
 int strip_volume(const char* name, char* namecopy);
 #endif
 
+#ifndef __PCTOOL__
+bool file_exists(const char *file);
+bool dir_exists(const char *path);
+#endif
+
 #endif /* __INCLUDE_FILEFUNCS_H_ */
diff --git a/firmware/export/paths.h b/firmware/export/paths.h
new file mode 100644
index 0000000..cd87888
--- /dev/null
+++ b/firmware/export/paths.h
@@ -0,0 +1,132 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __PATHS_H__
+#define __PATHS_H__
+
+#include <stdbool.h>
+#include "autoconf.h"
+#include "string-extra.h"
+
+/* flags for get_user_file_path() */
+/* whether you need write access to that file/dir, especially true
+ * for runtime generated files (config.cfg) */
+#define NEED_WRITE          (1<<0)
+/* file or directory? */
+#define IS_FILE             (1<<1)
+/* make sure the path is copied into the passed buffer (it may return
+ * the passed path directly otherwise, e.g. always on target builds) */
+#define FORCE_BUFFER_COPY   (1<<2)
+
+
+
+/* name of directory where configuration, fonts and other data
+ * files are stored */
+#ifdef __PCTOOL__
+#undef ROCKBOX_DIR
+#undef ROCKBOX_DIR_LEN
+#undef WPS_DIR
+#define ROCKBOX_DIR "."
+#define ROCKBOX_DIR_LEN 1
+#else
+
+/* ROCKBOX_DIR is now defined in autoconf.h for flexible build types */
+#ifndef ROCKBOX_DIR
+#error ROCKBOX_DIR not defined (should be in autoconf.h)
+#endif
+#define ROCKBOX_DIR_LEN (sizeof(ROCKBOX_DIR)-1)
+#endif /* def __PCTOOL__ */
+
+#ifndef APPLICATION
+
+/* make sure both are the same for native builds */
+#undef ROCKBOX_LIBRARY_PATH
+#define ROCKBOX_LIBRARY_PATH ROCKBOX_DIR
+
+#define PLUGIN_DIR          ROCKBOX_DIR "/rocks"
+#define CODECS_DIR          ROCKBOX_DIR "/codecs"
+
+#define REC_BASE_DIR        "/"
+#define PLAYLIST_CATALOG_DEFAULT_DIR "/Playlists"
+
+#ifndef PLUGIN
+static inline __attribute__((always_inline)) const char* get_user_file_path(const char *path,
+                               unsigned flags,
+                               char* buf,
+                               const size_t bufsize)
+{
+    if (flags & FORCE_BUFFER_COPY)
+    {
+        strlcpy(buf, path, bufsize);
+        return buf;
+    }
+    return path;
+}
+#endif
+
+#define paths_init()
+#else /* application */
+
+#define PLUGIN_DIR          ROCKBOX_LIBRARY_PATH "/rockbox/rocks"
+#define CODECS_DIR          ROCKBOX_LIBRARY_PATH "/rockbox/codecs"
+
+#define REC_BASE_DIR        ROCKBOX_DIR  "/"
+#define PLAYLIST_CATALOG_DEFAULT_DIR ROCKBOX_DIR "/Playlists"
+
+extern void paths_init(void);
+extern const char* get_user_file_path(const char *path,
+                               unsigned flags,
+                               char* buf,
+                               const size_t bufsize);
+#endif /* APPLICATION */
+
+#define LANG_DIR            ROCKBOX_DIR "/langs"
+
+#define PLUGIN_GAMES_DIR    PLUGIN_DIR "/games"
+#define PLUGIN_APPS_DIR     PLUGIN_DIR "/apps"
+#define PLUGIN_DEMOS_DIR    PLUGIN_DIR "/demos"
+#define VIEWERS_DIR         PLUGIN_DIR "/viewers"
+
+
+#define WPS_DIR             ROCKBOX_DIR "/wps"
+#define SBS_DIR             WPS_DIR
+#define THEME_DIR           ROCKBOX_DIR "/themes"
+#define FONT_DIR            ROCKBOX_DIR "/fonts"
+#define ICON_DIR            ROCKBOX_DIR "/icons"
+
+#define BACKDROP_DIR        ROCKBOX_DIR "/backdrops"
+#define EQS_DIR             ROCKBOX_DIR "/eqs"
+
+/* need to fix this once the application gets record/radio abilities */
+#define RECPRESETS_DIR      ROCKBOX_DIR "/recpresets"
+#define FMPRESET_PATH       ROCKBOX_DIR "/fmpresets"
+
+#define DIRCACHE_FILE       ROCKBOX_DIR "/dircache.dat"
+#define CODEPAGE_DIR        ROCKBOX_DIR "/codepages"
+
+#define VIEWERS_CONFIG      ROCKBOX_DIR "/viewers.config"
+#define CONFIGFILE          ROCKBOX_DIR "/config.cfg"
+#define FIXEDSETTINGSFILE   ROCKBOX_DIR "/fixed.cfg"
+
+#define PLAYLIST_CONTROL_FILE   ROCKBOX_DIR "/.playlist_control"
+#define NVRAM_FILE              ROCKBOX_DIR "/nvram.bin"
+#define GLYPH_CACHE_FILE        ROCKBOX_DIR "/.glyphcache"
+#endif /* __PATHS_H__ */
diff --git a/firmware/font.c b/firmware/font.c
index f158471..d260664 100644
--- a/firmware/font.c
+++ b/firmware/font.c
@@ -36,6 +36,7 @@
 #include "panic.h"
 #include "rbunicode.h"
 #include "diacritic.h"
+#include "paths.h"
 
 #define MAX_FONTSIZE_FOR_16_BIT_OFFSETS 0xFFDB
 
@@ -56,7 +57,6 @@
 #define FONT_HEADER_SIZE 36
 #endif
 
-#define GLYPH_CACHE_FILE ROCKBOX_DIR"/.glyphcache"
 
 #ifndef BOOTLOADER
 /* Font cache includes */
@@ -606,12 +606,13 @@ void glyph_cache_save(struct font* pf)
         pf = &font_ui;
     if (pf->fd >= 0 && pf == &font_ui) 
     {
-#ifdef WPSEDITOR
-        cache_fd = open(GLYPH_CACHE_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666);
-#else
-        cache_fd = creat(GLYPH_CACHE_FILE, 0666);
-#endif
-        if (cache_fd < 0) return;
+        char path[MAX_PATH];
+        const char *file = get_user_file_path(GLYPH_CACHE_FILE, IS_FILE|NEED_WRITE,
+                                       path, sizeof(path));
+
+        cache_fd = open(file, O_WRONLY|O_CREAT|O_TRUNC, 0666);
+        if (cache_fd < 0)
+            return;
 
         lru_traverse(&pf->cache._lru, glyph_file_write);
 
@@ -630,9 +631,10 @@ static void glyph_cache_load(struct font* pf)
         int fd;
         unsigned char tmp[2];
         unsigned short ch;
+        char path[MAX_PATH];
 
-        fd = open(GLYPH_CACHE_FILE, O_RDONLY|O_BINARY);
-
+        fd = open(get_user_file_path(GLYPH_CACHE_FILE, IS_FILE|NEED_WRITE,
+                                     path, sizeof(path)), O_RDONLY|O_BINARY);
         if (fd >= 0) {
 
             while (read(fd, tmp, 2) == 2) {
diff --git a/firmware/include/dircache.h b/firmware/include/dircache.h
index 4472d5f..650b926 100644
--- a/firmware/include/dircache.h
+++ b/firmware/include/dircache.h
@@ -27,7 +27,6 @@
 
 #define DIRCACHE_RESERVE  (1024*64)
 #define DIRCACHE_LIMIT    (1024*1024*6)
-#define DIRCACHE_FILE     ROCKBOX_DIR"/dircache.dat"
 
 #define DIRCACHE_APPFLAG_TAGCACHE  0x0001
 
diff --git a/firmware/include/file.h b/firmware/include/file.h
index 91b701d..946dc5b 100644
--- a/firmware/include/file.h
+++ b/firmware/include/file.h
@@ -22,13 +22,17 @@
 #ifndef _FILE_H_
 #define _FILE_H_
 
-#undef MAX_PATH /* this avoids problems when building simulator */
-#define MAX_PATH 260
-
 #include <sys/types.h>
 #include "config.h"
 #include "gcc_extensions.h"
 
+#undef MAX_PATH /* this avoids problems when building simulator */
+#if (CONFIG_PLATFORM & PLATFORM_HOSTED) && !defined(SIMULATOR)
+#include <limits.h>
+#define MAX_PATH PATH_MAX
+#else
+#define MAX_PATH 260
+#endif
 #define MAX_OPEN_FILES 11
 
 #ifndef SEEK_SET
diff --git a/tools/buildzip.pl b/tools/buildzip.pl
index 0358459..ca39d8c 100755
--- a/tools/buildzip.pl
+++ b/tools/buildzip.pl
@@ -30,7 +30,6 @@ my $target_id; # passed in, not currently used
 my $rbdir=".rockbox"; # can be changed for special builds
 my $app;
 
-
 sub glob_mkdir {
     my ($dir) = @_;
     mkpath ($dir, $verbose, 0777);
@@ -607,6 +606,10 @@ sub runone {
 
     # in the app the the layout is different (no .rockbox, but bin/lib/share)
     $app = ($modelname eq "application");
+    unless ($app) {
+        #rbdir starts with '/', strip it
+        $rbdir = substr($rbdir, 1);
+    }
 
     # build a full install .rockbox ($rbdir) directory
     buildzip($target, $fonts);
diff --git a/tools/configure b/tools/configure
index 9f7c63f..8409cb0 100755
--- a/tools/configure
+++ b/tools/configure
@@ -19,7 +19,10 @@ use_bootchart="#undef DO_BOOTCHART"
 
 scriptver=`echo '$Revision$' | sed -e 's:\\$::g' -e 's/Revision: //'`
 
-rbdir=".rockbox"
+rbdir="/.rockbox"
+need_full_path=
+ROCKBOX_BINARY_PATH="/tmp"
+ROCKBOX_LIBRARY_PATH="/tmp"
   
 #
 # Begin Function Definitions
@@ -2604,7 +2607,19 @@ fi
     target_id=100
     modelname="application"
     target="-DAPPLICATION"
-    memory=32
+
+    if [ -z "$PREFIX" ]; then
+        rbdir="/usr/local/share/rockbox"
+        ROCKBOX_BINARY_PATH="/usr/local/bin"
+        ROCKBOX_LIBRARY_PATH="/usr/local/lib"
+    else
+        rbdir=`realpath $PREFIX/share/rockbox`
+        ROCKBOX_BINARY_PATH="$PREFIX/bin"
+        ROCKBOX_LIBRARY_PATH="$PREFIX/lib"
+    fi
+    need_full_path="yes"
+
+    memory=8
     uname=`uname`
     simcc "sdl-app"
     tool="cp "
@@ -3000,7 +3015,15 @@ else
 fi
 
 if [ "$ARG_RBDIR" ]; then
-  rbdir=$ARG_RBDIR
+  if [ "$need_full_path" = "yes" ]; then
+    rbdir=`realpath $ARG_RBDIR`
+  else # prepend '/' if needed
+    if [ -z `echo $ARG_RBDIR | grep -P '/.*'` ]; then
+        rbdir="/"$ARG_RBDIR
+    else
+        rbdir=$ARG_RBDIR
+    fi
+  fi
   echo "Using alternate rockbox dir: ${rbdir}"
 fi
 
@@ -3011,6 +3034,8 @@ sed > autoconf.h \
  -e "s<@config_rtc@<$config_rtc<g" \
  -e "s<@have_rtc_alarm@<$have_rtc_alarm<g" \
  -e "s<@RBDIR@<${rbdir}<g" \
+ -e "s<@binpath@<`realpath ${ROCKBOX_BINARY_PATH}`<g" \
+ -e "s<@libpath@<`realpath ${ROCKBOX_LIBRARY_PATH}`<g" \
  -e "s<@have_backlight@<$have_backlight<g" \
  -e "s<@have_fmradio_in@<$have_fmradio_in<g" \
  -e "s<@have_ata_poweroff@<$have_ata_poweroff<g" \
@@ -3042,7 +3067,9 @@ sed > autoconf.h \
 @have_rtc_alarm@
 
 /* root of Rockbox */
-#define ROCKBOX_DIR "/@RBDIR@"
+#define ROCKBOX_DIR "@RBDIR@"
+#define ROCKBOX_BINARY_PATH "@binpath@"
+#define ROCKBOX_LIBRARY_PATH "@libpath@"
 
 #endif /* __BUILD_AUTOCONF_H */
 EOF
@@ -3155,6 +3182,8 @@ sed > Makefile \
  -e "s<@LANGS@<${buildlangs}<g" \
  -e "s<@USE_ELF@<${USE_ELF}<g" \
  -e "s<@RBDIR@<${rbdir}<g" \
+ -e "s<@binpath@<${ROCKBOX_BINARY_PATH}<g" \
+ -e "s<@libpath@<${ROCKBOX_LIBRARY_PATH}<g" \
  -e "s<@PREFIX@<$PREFIX<g" \
  -e "s<@CMDLINE@<$cmdline<g" \
  -e "s<@SDLCONFIG@<$sdl<g" \
@@ -3222,6 +3251,8 @@ export ENC_OPTS=@ENC_OPTS@
 export ENCODER=@ENCODER@
 export USE_ELF=@USE_ELF@
 export RBDIR=@RBDIR@
+export ROCKBOX_BINARY_PATH=@binpath@
+export ROCKBOX_LIBRARY_PATH=@libpath@
 export SDLCONFIG=@SDLCONFIG@
 
 CONFIGURE_OPTIONS=@CMDLINE@
diff --git a/tools/root.make b/tools/root.make
index e53c452..8f31137 100644
--- a/tools/root.make
+++ b/tools/root.make
@@ -24,16 +24,22 @@ TOOLS = $(TOOLSDIR)/rdf2binary $(TOOLSDIR)/convbdf \
 
 
 ifeq (,$(PREFIX))
-ifeq ($(APP_TYPE),sdl-sim)
+ifdef APP_TYPE
 # for sims, set simdisk/ as default
-PREFIX = simdisk
-INSTALL = --install="$(PREFIX)"
+ifeq ($(APP_TYPE),sdl-sim)
+RBPREFIX = simdisk
+else ifeq ($(APP_TYPE),sdl-app)
+RBPREFIX = /usr/local
+endif
+
+INSTALL = --install="$(RBPREFIX)"
 else
 # /dev/null as magic to tell it wasn't set, error out later in buildzip.pl
 INSTALL = --install=/dev/null
 endif
 else
-INSTALL = --install="$(PREFIX)"
+RBPREFIX = $(PREFIX)
+INSTALL = --install="$(RBPREFIX)"
 endif
 
 RBINFO = $(BUILDDIR)/rockbox-info.txt
@@ -278,8 +284,8 @@ voice: voicetools $(BUILDDIR)/apps/features
 endif
 
 bininstall: $(BUILDDIR)/$(BINARY)
-	@echo "Installing your rockbox binary in your '$(PREFIX)' dir"
-	$(SILENT)cp $(BINARY) "$(PREFIX)/.rockbox/"
+	@echo "Installing your rockbox binary in your '$(RBPREFIX)' dir"
+	$(SILENT)cp $(BINARY) "$(RBPREFIX)/.rockbox/"
 
 install:
 	@echo "Installing your build in your '$(PREFIX)' dir"
@@ -349,4 +355,4 @@ ifneq (reconf,$(MAKECMDGOALS))
 endif
 
 reconf:
-	$(SILENT$)PREFIX=$(PREFIX) $(TOOLSDIR)/configure $(CONFIGURE_OPTIONS)
+	$(SILENT$)$(TOOLSDIR)/configure $(CONFIGURE_OPTIONS)
diff --git a/uisimulator/common/io.c b/uisimulator/common/io.c
index bdcc7e6..e4baefd 100644
--- a/uisimulator/common/io.c
+++ b/uisimulator/common/io.c
@@ -40,9 +40,6 @@
 #include "dir-win32.h"
 #endif
 
-#define MAX_PATH 260
-#define MAX_OPEN_FILES 11
-
 #include <fcntl.h>
 #include <SDL.h>
 #include <SDL_thread.h>
@@ -52,7 +49,16 @@
 #include "config.h"
 #include "ata.h" /* for IF_MV2 et al. */
 #include "thread-sdl.h"
+#include "paths.h"
 
+#undef MAX_PATH /* this avoids problems when building simulator */
+#if (CONFIG_PLATFORM & PLATFORM_HOSTED) && !defined(SIMULATOR)
+#include <limits.h>
+#define MAX_PATH PATH_MAX
+#else
+#define MAX_PATH 260
+#endif
+#define MAX_OPEN_FILES 11
 
 /* Windows (and potentially other OSes) distinguish binary and text files.
  * Define a dummy for the others. */
@@ -255,7 +261,7 @@ static ssize_t io_trigger_and_wait(int cmd)
     return result;
 }
 
-#ifndef __PCTOOL__
+#if !defined(__PCTOOL__) && !defined(APPLICATION)
 static const char *get_sim_pathname(const char *name)
 {
     static char buffer[MAX_PATH]; /* sufficiently big */
@@ -520,7 +526,6 @@ int sim_fsync(int fd)
 void *sim_codec_load_ram(char* codecptr, int size, void **pd)
 {
     void *hdr;
-    char name[MAX_PATH];
     char path[MAX_PATH];
     int fd;
     int codec_count;
@@ -536,8 +541,9 @@ void *sim_codec_load_ram(char* codecptr, int size, void **pd)
        to find an unused filename */
     for (codec_count = 0; codec_count < 10; codec_count++)
     {
-        snprintf(name, sizeof(name), "/_temp_codec%d.dll", codec_count);
-        snprintf(path, sizeof(path), "%s", get_sim_pathname(name));
+        char name[MAX_PATH];
+        const char *_name = get_user_file_path(ROCKBOX_DIR, 0, name, sizeof(name));
+        snprintf(path, sizeof(path), "%s/_temp_codec%d.dll", get_sim_pathname(_name), codec_count);
         fd = OPEN(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRWXU);
         if (fd >= 0)
             break;  /* Created a file ok */
