From 1b530cd3e9b1de3a5912e17cd4245b22bf5f2ceb Mon Sep 17 00:00:00 2001 From: kugel Date: Sun, 1 Aug 2010 16:15:27 +0000 Subject: [PATCH] Rockbox as an application: add get_user_file_path(). For RaaA it evaluates user paths at runtime. For everything but codecs/plugins it will give the path under $HOME/.config/rockbox.org if write access is needed or if the file/folder in question exists there (otherwise it gives /usr/local/share/rockbox). This allows for installing themes under $HOME as well as having config.cfg and other important files there while installing the application (and default themes) under /usr/local. On the DAPs it's a no-op, returing /.rockbox directly. Not converted to use get_user_file_path() are plugins themselves, because RaaA doesn't build plugins yet. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27656 a1c6a512-1295-4272-9138-f99709370657 --- apps/codecs.c | 4 +- apps/filetree.c | 5 +- apps/filetypes.c | 7 +- apps/gui/skin_engine/skin_fonts.c | 2 +- apps/gui/skin_engine/skin_parser.c | 3 +- apps/gui/theme_settings.c | 4 +- apps/main.c | 17 +++-- apps/menus/main_menu.c | 5 +- apps/menus/theme_menu.c | 4 +- apps/misc.c | 29 -------- apps/misc.h | 2 - apps/playlist.c | 12 +++- apps/playlist_catalog.c | 10 ++- apps/plugin.c | 1 + apps/plugin.h | 1 + apps/radio/presets.c | 1 + apps/radio/radioart.c | 1 + apps/recorder/albumart.c | 1 + apps/recorder/recording.c | 2 +- apps/root_menu.c | 10 ++- apps/scrobbler.c | 2 +- apps/settings.c | 47 ++++++++---- apps/settings.h | 45 +----------- apps/tagcache.c | 142 ++++++++++++++++++++++++++----------- apps/tree.c | 4 +- firmware/SOURCES | 3 + firmware/common/dircache.c | 11 ++- firmware/common/filefuncs.c | 37 ++++++++++ firmware/common/rbpaths.c | 84 ++++++++++++++++++++++ firmware/common/unicode.c | 4 +- firmware/export/filefuncs.h | 5 ++ firmware/export/rbpaths.h | 132 ++++++++++++++++++++++++++++++++++ firmware/font.c | 20 +++--- firmware/include/dircache.h | 1 - firmware/include/file.h | 5 +- tools/buildzip.pl | 7 +- tools/configure | 49 +++++++++++-- tools/root.make | 20 ++++-- uisimulator/common/io.c | 16 +++-- wps/WPSLIST | 44 ++++++------ wps/wpsbuild.pl | 69 ++++++++++-------- 41 files changed, 620 insertions(+), 248 deletions(-) create mode 100644 firmware/common/rbpaths.c create mode 100644 firmware/export/rbpaths.h diff --git a/apps/codecs.c b/apps/codecs.c index 154faa3f3..29a664425 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 460ab9e45..fa942b263 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 4be2437a2..67a4c176f 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 92a6a22cc..b3b4df2c9 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 e5c89ab2b..d0194c669 100644 --- a/apps/gui/skin_engine/skin_parser.c +++ b/apps/gui/skin_engine/skin_parser.c @@ -1452,7 +1452,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 e9862eda3..a975c218c 100644 --- a/apps/gui/theme_settings.c +++ b/apps/gui/theme_settings.c @@ -97,7 +97,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 6c6d09cba..67cd6d2f0 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 a64b1f8e4..1d22dba7e 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 f8fb06b22..c6553728a 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 c378133ab..39f17be29 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 58a9085d5..0de68a001 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 4a6db883f..2896f62e7 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 = ¤t_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 f9a43da41..2fbffdaa3 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 81ba006af..b3baea757 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 cf1fd7742..5ee18d007 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 aa265bcc7..e900afe73 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 7ba9881d8..85397c16b 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 5eca71354..6b4357669 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 ab7e7c9b3..0098d6bf7 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 53c522a77..7965673b6 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 8d9f694ec..9b0decfb6 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 6f1fd7ad2..58585d60e 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -25,6 +25,7 @@ #include #include "inttypes.h" #include "config.h" +#include "rbpaths.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 63305b5ae..7deb2def4 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -33,6 +33,7 @@ #if CONFIG_CODEC == SWCODEC #include "audio.h" #endif +#include "rbpaths.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 1094c92a9..898263ef2 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 d63ddd448..ed8e4d20b 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 b4f5301a8..d8cfadef1 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/rbpaths.c +#endif common/strcasecmp.c common/strcasestr.c common/strnatcmp.c diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c index 906527f8f..7b2cdd1d7 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 ca9113250..c05826709 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/rbpaths.c b/firmware/common/rbpaths.c new file mode 100644 index 000000000..69bc1387e --- /dev/null +++ b/firmware/common/rbpaths.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 /* snprintf */ +#include +#include "rbpaths.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 4ef6eaae2..25d4a9129 100644 --- a/firmware/common/unicode.c +++ b/firmware/common/unicode.c @@ -27,16 +27,16 @@ */ #include +#include "config.h" #include "file.h" #include "debug.h" #include "rbunicode.h" -#include "config.h" +#include "rbpaths.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 130c5ff4b..3745c6bee 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/rbpaths.h b/firmware/export/rbpaths.h new file mode 100644 index 000000000..cd87888ce --- /dev/null +++ b/firmware/export/rbpaths.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 +#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 f1584713e..b8ad76ec3 100644 --- a/firmware/font.c +++ b/firmware/font.c @@ -36,6 +36,7 @@ #include "panic.h" #include "rbunicode.h" #include "diacritic.h" +#include "rbpaths.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 4472d5fbe..650b92632 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 91b701d6d..a9d1d05a1 100644 --- a/firmware/include/file.h +++ b/firmware/include/file.h @@ -22,13 +22,12 @@ #ifndef _FILE_H_ #define _FILE_H_ -#undef MAX_PATH /* this avoids problems when building simulator */ -#define MAX_PATH 260 - #include #include "config.h" #include "gcc_extensions.h" +#undef MAX_PATH /* this avoids problems when building simulator */ +#define MAX_PATH 260 #define MAX_OPEN_FILES 11 #ifndef SEEK_SET diff --git a/tools/buildzip.pl b/tools/buildzip.pl index 0358459c9..7a127dea2 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); @@ -550,7 +549,7 @@ STOP if(-d "$ROOT/wps") { my $wps_build_cmd="perl $ROOT/wps/wpsbuild.pl "; $wps_build_cmd=$wps_build_cmd."-v " if $verbose; - $wps_build_cmd=$wps_build_cmd." --rbdir=$rbdir -r $ROOT -m $modelname $ROOT/wps/WPSLIST $target"; + $wps_build_cmd=$wps_build_cmd." --tempdir=$temp_dir --rbdir=$rbdir -r $ROOT -m $modelname $ROOT/wps/WPSLIST $target"; print "wpsbuild: $wps_build_cmd\n" if $verbose; system("$wps_build_cmd"); print "wps_build_cmd: done\n" if $verbose; @@ -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 0896e5b69..ce23c2a96 100755 --- a/tools/configure +++ b/tools/configure @@ -19,7 +19,12 @@ use_bootchart="#undef DO_BOOTCHART" scriptver=`echo '$Revision$' | sed -e 's:\\$::g' -e 's/Revision: //'` -rbdir=".rockbox" +rbdir="/.rockbox" +need_full_path= +bindir= +libdir= +bindir_full= +libdir_full= # # Begin Function Definitions @@ -2603,7 +2608,27 @@ fi target_id=100 modelname="application" target="-DAPPLICATION" - memory=32 + + if [ -z "$PREFIX" ]; then + rbdir="/usr/local/share/rockbox" + bindir="/usr/local/bin" + bindir_full=$bindir + libdir="/usr/local/lib" + libdir_full=$libdir + else + rbdir=`realpath $PREFIX/share/rockbox` + bindir="$PREFIX/bin" + libdir="$PREFIX/lib" + if [ -d bindir ]; then + bindir_full=`realpath $bindir` + fi + if [ -d libdir ]; then + libdir_full=`realpath $libdir` + fi + fi + need_full_path="yes" + + memory=8 uname=`uname` simcc "sdl-app" tool="cp " @@ -2999,7 +3024,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 @@ -3010,6 +3043,8 @@ sed > autoconf.h \ -e "s<@config_rtc@<$config_rtc 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 @@ -3154,6 +3191,8 @@ sed > Makefile \ -e "s<@LANGS@<${buildlangs} #include #include @@ -52,7 +49,12 @@ #include "config.h" #include "ata.h" /* for IF_MV2 et al. */ #include "thread-sdl.h" +#include "rbpaths.h" +/* keep this in sync with file.h! */ +#undef MAX_PATH /* this avoids problems when building simulator */ +#define MAX_PATH 260 +#define MAX_OPEN_FILES 11 /* Windows (and potentially other OSes) distinguish binary and text files. * Define a dummy for the others. */ @@ -255,7 +257,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 +522,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 +537,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 */ diff --git a/wps/WPSLIST b/wps/WPSLIST index 13cb26386..3068f4851 100644 --- a/wps/WPSLIST +++ b/wps/WPSLIST @@ -346,30 +346,30 @@ selector type.160x128x2: bar (inverse) selector type.138x110x2: bar (inverse) #icons -iconset.320x240x16: /.rockbox/icons/tango_small.bmp -iconset.128x128x16: /.rockbox/icons/tango_small.bmp -iconset.132x80x16: /.rockbox/icons/tango_small.bmp -iconset.138x110x2: /.rockbox/icons/tango_small_mono.bmp -iconset.160x128x16: /.rockbox/icons/tango_small.bmp -iconset.160x128x2: /.rockbox/icons/tango_small_mono.bmp -iconset.176x132x16: /.rockbox/icons/tango_small.bmp -iconset.176x220x16: /.rockbox/icons/tango_small.bmp -iconset.220x176x16: /.rockbox/icons/tango_small.bmp -iconset.240x320x16: /.rockbox/icons/tango_small.bmp -iconset.240x400x16: /.rockbox/icons/tango_small.bmp +iconset.320x240x16: icons/tango_small.bmp +iconset.128x128x16: icons/tango_small.bmp +iconset.132x80x16: icons/tango_small.bmp +iconset.138x110x2: icons/tango_small_mono.bmp +iconset.160x128x16: icons/tango_small.bmp +iconset.160x128x2: icons/tango_small_mono.bmp +iconset.176x132x16: icons/tango_small.bmp +iconset.176x220x16: icons/tango_small.bmp +iconset.220x176x16: icons/tango_small.bmp +iconset.240x320x16: icons/tango_small.bmp +iconset.240x400x16: icons/tango_small.bmp #viewer icons -viewers iconset.320x240x16: /.rockbox/icons/tango_small_viewers.bmp -viewers iconset.128x128x16: /.rockbox/icons/tango_small_viewers.bmp -viewers iconset.132x80x16: /.rockbox/icons/tango_small_viewers.bmp -viewers iconset.138x110x2: /.rockbox/icons/tango_small_viewers_mono.bmp -viewers iconset.160x128x16: /.rockbox/icons/tango_small_viewers.bmp -viewers iconset.160x128x2: /.rockbox/icons/tango_small_viewers_mono.bmp -viewers iconset.176x132x16: /.rockbox/icons/tango_small_viewers.bmp -viewers iconset.176x220x16: /.rockbox/icons/tango_small_viewers.bmp -viewers iconset.220x176x16: /.rockbox/icons/tango_small_viewers.bmp -viewers iconset.240x320x16: /.rockbox/icons/tango_small_viewers.bmp -viewers iconset.240x400x16: /.rockbox/icons/tango_small_viewers.bmp +viewers iconset.320x240x16: icons/tango_small_viewers.bmp +viewers iconset.128x128x16: icons/tango_small_viewers.bmp +viewers iconset.132x80x16: icons/tango_small_viewers.bmp +viewers iconset.138x110x2: icons/tango_small_viewers_mono.bmp +viewers iconset.160x128x16: icons/tango_small_viewers.bmp +viewers iconset.160x128x2: icons/tango_small_viewers_mono.bmp +viewers iconset.176x132x16: icons/tango_small_viewers.bmp +viewers iconset.176x220x16: icons/tango_small_viewers.bmp +viewers iconset.220x176x16: icons/tango_small_viewers.bmp +viewers iconset.240x320x16: icons/tango_small_viewers.bmp +viewers iconset.240x400x16: icons/tango_small_viewers.bmp # Whether the WPS is designed to have the statusbar on or off Statusbar: top diff --git a/wps/wpsbuild.pl b/wps/wpsbuild.pl index f07ad6dc0..7e54f109c 100755 --- a/wps/wpsbuild.pl +++ b/wps/wpsbuild.pl @@ -14,6 +14,7 @@ use Getopt::Long qw(:config pass_through); # pass_through so not confused by -DT my $ROOT=".."; my $verbose; my $rbdir=".rockbox"; +my $tempdir=".rockbox"; my $wpslist; my $target; my $modelname; @@ -23,6 +24,7 @@ GetOptions ( 'r|root=s' => \$ROOT, 'm|modelname=s' => \$modelname, 'v|verbose' => \$verbose, 'rbdir=s' => \$rbdir, # If we want to put in a different directory + 'tempdir=s' => \$tempdir, # override .rockbox temporary dir ); ($wpslist, $target) = @ARGV; @@ -72,7 +74,7 @@ my $has_remote; if(!$wpslist) { print "Usage: wpsbuilds.pl \n", "Run this script in the root of the target build, and it will put all the\n", - "stuff in $rbdir/wps/\n"; + "stuff in $tempdir/wps/\n and build the cfg according to $rbdir"; exit; } @@ -135,15 +137,15 @@ sub mkdirs { my $wpsdir = $wps; $wpsdir =~ s/\.(r|)wps//; - mkdir "$rbdir/wps", 0777; - mkdir "$rbdir/themes", 0777; + mkdir "$tempdir/wps", 0777; + mkdir "$tempdir/themes", 0777; - if( -d "$rbdir/wps/$wpsdir") { + if( -d "$tempdir/wps/$wpsdir") { #print STDERR "wpsbuild warning: directory wps/$wpsdir already exists!\n"; } else { - mkdir "$rbdir/wps/$wpsdir", 0777; + mkdir "$tempdir/wps/$wpsdir", 0777; } } @@ -153,7 +155,7 @@ sub copybackdrop if ($backdrop ne '') { my $dst = $backdrop; $dst =~ s/(\.[0-9]*x[0-9]*x[0-9]*)//; - my $cmd = "cp $ROOT/$backdrop $rbdir/$dst"; + my $cmd = "cp $ROOT/$backdrop $tempdir/$dst"; `$cmd`; } } @@ -164,19 +166,19 @@ sub copythemefont my $o = $_[0]; $o =~ s/\.fnt/\.bdf/; - mkdir "$rbdir/fonts"; - my $cmd ="$ROOT/tools/convbdf -f -o \"$rbdir/fonts/$_[0]\" \"$ROOT/fonts/$o\" "; + mkdir "$tempdir/fonts"; + my $cmd ="$ROOT/tools/convbdf -f -o \"$tempdir/fonts/$_[0]\" \"$ROOT/fonts/$o\" "; `$cmd`; } sub copythemeicon { #copy the icon specified by the theme - if ($iconset ne '') { - $iconset =~ s/.rockbox/$rbdir/; - $iconset =~ /\/(.*icons\/(.*))/i; - `cp $ROOT/icons/$2 $1`; + my $tempicon = $tempdir . "/" . $iconset; + $iconset = $rbdir . "/" . $iconset; + $tempicon =~ /\/.*icons\/(.*)/i; + `cp $ROOT/icons/$1 $tempicon`; } } @@ -185,9 +187,10 @@ sub copythemeviewericon #copy the viewer icon specified by the theme if ($viewericon ne '') { - $viewericon =~ s/.rockbox/$rbdir/; - $viewericon =~ /\/(.*icons\/(.*))/i; - `cp $ROOT/icons/$2 $1`; + my $tempviewericon = $tempdir . "/" . $viewericon; + $viewericon = $rbdir . "/" . $viewericon; + $tempviewericon =~ /\/.*icons\/(.*)/i; + `cp $ROOT/icons/$1 $tempviewericon`; } } @@ -209,20 +212,20 @@ sub copywps # system("cp $dir/$wps .rockbox/wps/"); # check for .WIDTHxHEIGHTxDEPTH.sbs if (-e "$dir/$__sb") { - system("cp $dir/$__sb $rbdir/wps/$sbs"); + system("cp $dir/$__sb $tempdir/wps/$sbs"); } # check for .WIDTHxHEIGHTxDEPTH..sbs and overwrite the # previous sb if needed $__sb = $sbs_prefix . "." . $req_size . "." . $modelname . ".sbs"; if (-e "$dir/$__sb") { - system("cp $dir/$__sb $rbdir/wps/$sbs"); + system("cp $dir/$__sb $tempdir/wps/$sbs"); } if (-e "$dir/$req_t_wps" ) { - system("cp $dir/$req_t_wps $rbdir/wps/$wps"); + system("cp $dir/$req_t_wps $tempdir/wps/$wps"); } elsif (-e "$dir/$req_g_wps") { - system("cp $dir/$req_g_wps $rbdir/wps/$wps"); + system("cp $dir/$req_g_wps $tempdir/wps/$wps"); open(WPSFILE, "$dir/$req_g_wps"); while () { @@ -233,12 +236,12 @@ sub copywps if ($#filelist >= 0) { if (-e "$dir/$wps_prefix/$req_size") { foreach $file (@filelist) { - system("cp $dir/$wps_prefix/$req_size/$file $rbdir/wps/$wps_prefix/"); + system("cp $dir/$wps_prefix/$req_size/$file $tempdir/wps/$wps_prefix/"); } } elsif (-e "$dir/$wps_prefix") { foreach $file (@filelist) { - system("cp $dir/$wps_prefix/$file $rbdir/wps/$wps_prefix/"); + system("cp $dir/$wps_prefix/$file $tempdir/wps/$wps_prefix/"); } } else { @@ -265,35 +268,35 @@ sub buildcfg { \# $cfg generated by wpsbuild.pl \# $wps is made by $author \# -wps: /$rbdir/wps/$wps +wps: $rbdir/wps/$wps MOO ; if(defined($sbs)) { if ($sbs eq '') { push @out, "sbs: -\n"; } else { - push @out, "sbs: /$rbdir/wps/$sbs\n"; + push @out, "sbs: $rbdir/wps/$sbs\n"; } } if(defined($rsbs) && $has_remote) { if ($rsbs eq '') { push @out, "rsbs: -\n"; } else { - push @out, "rsbs: /$rbdir/wps/$rsbs\n"; + push @out, "rsbs: $rbdir/wps/$rsbs\n"; } } if($font) { if ($font eq '') { push @out, "font: -\n"; } else { - push @out, "font: /$rbdir/fonts/$font\n"; + push @out, "font: $rbdir/fonts/$font\n"; } } if(defined($remotefont) && $has_remote) { if ($remotefont eq '') { push @out, "remote font: -\n"; } else { - push @out, "remote font: /$rbdir/fonts/$remotefont\n"; + push @out, "remote font: $rbdir/fonts/$remotefont\n"; } } if($fgcolor && $main_depth > 2) { @@ -314,7 +317,7 @@ MOO } else { # clip resolution from filename $backdrop =~ s/(\.[0-9]*x[0-9]*x[0-9]*)//; - push @out, "backdrop: /$rbdir/$backdrop\n"; + push @out, "backdrop: $rbdir/$backdrop\n"; } } if($lineselectstart && $main_depth > 2) { @@ -354,7 +357,7 @@ MOO if ($rwps eq '') { push @out, "rwps: -\n"; } else { - push @out, "rwps: /$rbdir/wps/$rwps\n"; + push @out, "rwps: $rbdir/wps/$rwps\n"; } } if(defined($listviewport)) { @@ -371,11 +374,11 @@ MOO push @out, "remote ui viewport: $listviewport\n"; } } - if(-f "$rbdir/wps/$cfg") { + if(-f "$tempdir/wps/$cfg") { print STDERR "wpsbuild warning: wps/$cfg already exists!\n"; } else { - open(CFG, ">$rbdir/themes/$cfg"); + open(CFG, ">$tempdir/themes/$cfg"); print CFG @out; close(CFG); } @@ -401,6 +404,12 @@ while() { # skip comment next; } + + # prefix $rbdir with / if needed (needed for the theme.cfg) + unless ($rbdir =~ /\/.*/) { + $rbdir = "/" . $rbdir; + } + if($l =~ /^ *<(r|)wps>/i) { $isrwps = $1; $within = 1; -- 2.11.4.GIT