From 9c0b2479f7025a84444adf08e3be8ced60dad013 Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Sun, 1 Aug 2010 16:15:27 +0000 Subject: 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 --- 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 +- 10 files changed, 284 insertions(+), 18 deletions(-) create mode 100644 firmware/common/rbpaths.c create mode 100644 firmware/export/rbpaths.h (limited to 'firmware') diff --git a/firmware/SOURCES b/firmware/SOURCES index b4f5301a84..d8cfadef11 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 906527f8f2..7b2cdd1d75 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 ca9113250a..c058267094 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 0000000000..69bc1387ef --- /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 4ef6eaae2b..25d4a9129e 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 130c5ff4be..3745c6bee3 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 0000000000..cd87888cef --- /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 f1584713ed..b8ad76ec3a 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 4472d5fbe0..650b92632d 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 91b701d6d2..a9d1d05a11 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 -- cgit v1.2.3