From af7aaae478b5c7382ae5505abab233a97aa3e658 Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Mon, 20 Jun 2011 20:12:42 +0000 Subject: Dircache: Don't expose struct dircache_entry and pointers into the cache, use IDs instead. Only integer IDs are exposed from dircache with this. This way the cache is isolated from other modules. This is needed for my buflib gsoc project. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30038 a1c6a512-1295-4272-9138-f99709370657 --- firmware/common/dircache.c | 73 ++++++++++++++++++++++++++++++++++++--------- firmware/common/file.c | 13 ++++---- firmware/common/filefuncs.c | 2 +- 3 files changed, 67 insertions(+), 21 deletions(-) (limited to 'firmware/common') diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c index 0f3c453ee7..bff9c2f4e7 100644 --- a/firmware/common/dircache.c +++ b/firmware/common/dircache.c @@ -57,7 +57,23 @@ #else #define MAX_OPEN_DIRS 8 #endif -static DIR_CACHED opendirs[MAX_OPEN_DIRS]; + +#define MAX_PENDING_BINDINGS 2 +struct fdbind_queue { + char path[MAX_PATH]; + int fd; +}; + +/* Exported structures. */ +struct dircache_entry { + struct dirinfo info; + struct dircache_entry *next; + struct dircache_entry *up; + struct dircache_entry *down; + long startcluster; + char *d_name; +}; + /* Cache Layout: * * x - array of struct dircache_entry @@ -75,7 +91,6 @@ static DIR_CACHED opendirs[MAX_OPEN_DIRS]; * total allocation size grows * |xxxxxxxx|rrrrrrrrr|dddddddd| */ -static struct dircache_entry *fd_bindings[MAX_OPEN_FILES]; /* this points to the beginnging of the buffer and the first entry */ static struct dircache_entry *dircache_root; /* these point to the start and end of the name buffer (d above) */ @@ -86,6 +101,9 @@ static char *dot, *dotdot; static struct dircache_entry *append_position; #endif +static DIR_CACHED opendirs[MAX_OPEN_DIRS]; +static struct dircache_entry *fd_bindings[MAX_OPEN_FILES]; + static bool dircache_initialized = false; static bool dircache_initializing = false; static bool thread_enabled = false; @@ -105,6 +123,11 @@ static int fdbind_idx = 0; /* --- Internal cache structure control functions --- */ +static inline struct dircache_entry* get_entry(int id) +{ + return &dircache_root[id]; +} + #ifdef HAVE_EEPROM_SETTINGS /** * Open the dircache file to save a snapshot on disk @@ -1012,14 +1035,36 @@ void dircache_disable(void) } /** - * Usermode function to return dircache_entry pointer to the given path. + * Usermode function to return dircache_entry index to the given path. */ -const struct dircache_entry *dircache_get_entry_ptr(const char *filename) +static int dircache_get_entry_id_ex(const char *filename, bool go_down) { if (!dircache_initialized || filename == NULL) - return NULL; + return -1; - return dircache_get_entry(filename, false); + struct dircache_entry* res = dircache_get_entry(filename, go_down); + return res ? res - dircache_root : -1; +} + +int dircache_get_entry_id(const char* filename) +{ + return dircache_get_entry_id_ex(filename, false); +} + +/** + * Internal: Get the startcluster for the index + */ +long _dircache_get_entry_startcluster(int id) +{ + return get_entry(id)->startcluster; +} + +/** + * Internal: Get the struct dirinfo for the index + */ +struct dirinfo* _dircache_get_entry_dirinfo(int id) +{ + return &get_entry(id)->info; } /* @@ -1050,13 +1095,13 @@ static size_t copy_path_helper(const struct dircache_entry *entry, char *buf, si * * Returns the size of the resulting string, or 0 if an error occured */ -size_t dircache_copy_path(const struct dircache_entry *entry, char *buf, size_t size) +size_t dircache_copy_path(int index, char *buf, size_t size) { - if (!size || !buf) + if (!size || !buf || index < 0) return 0; buf[0] = '/'; - size_t res = copy_path_helper(entry, buf, size); + size_t res = copy_path_helper(&dircache_root[index], buf, size); /* fixup trailing '/' */ buf[res] = '\0'; return res; @@ -1373,17 +1418,17 @@ DIR_CACHED* opendir_cached(const char* name) if (!dircache_initialized || is_disable_msg_pending()) { - pdir->internal_entry = NULL; + pdir->internal_entry = -1; pdir->regulardir = opendir_uncached(name); } else { pdir->regulardir = NULL; - pdir->internal_entry = dircache_get_entry(name, true); + pdir->internal_entry = dircache_get_entry_id_ex(name, true); pdir->theent.info.attribute = -1; /* used to make readdir_cached aware of the first call */ } - if (pdir->internal_entry == NULL && pdir->regulardir == NULL) + if (pdir->internal_entry == -1 && pdir->regulardir == NULL) { pdir->busy = false; return NULL; @@ -1394,7 +1439,7 @@ DIR_CACHED* opendir_cached(const char* name) struct dirent_cached* readdir_cached(DIR_CACHED* dir) { - struct dircache_entry *ce = dir->internal_entry; + struct dircache_entry *ce = get_entry(dir->internal_entry); struct dirent_uncached *regentry; if (!dir->busy) @@ -1430,7 +1475,7 @@ struct dirent_cached* readdir_cached(DIR_CACHED* dir) because that modifies the d_name pointer. */ dir->theent.startcluster = ce->startcluster; dir->theent.info = ce->info; - dir->internal_entry = ce; + dir->internal_entry = ce - dircache_root; //logf("-> %s", ce->d_name); return &dir->theent; diff --git a/firmware/common/file.c b/firmware/common/file.c index 8f6bfa051b..cfebd0622f 100644 --- a/firmware/common/file.c +++ b/firmware/common/file.c @@ -108,25 +108,26 @@ static int open_internal(const char* pathname, int flags, bool use_cache) #ifdef HAVE_DIRCACHE if (dircache_is_enabled() && !file->write && use_cache) { - const struct dircache_entry *ce; # ifdef HAVE_MULTIVOLUME int volume = strip_volume(pathname, pathnamecopy); # endif - ce = dircache_get_entry_ptr(pathname); - if (!ce) + int ce = dircache_get_entry_id(pathname); + if (ce < 0) { errno = ENOENT; file->busy = false; return -7; } + long startcluster = _dircache_get_entry_startcluster(ce); fat_open(IF_MV2(volume,) - ce->startcluster, + startcluster, &(file->fatfile), NULL); - file->size = ce->info.size; - file->attr = ce->info.attribute; + struct dirinfo *info = _dircache_get_entry_dirinfo(ce); + file->size = info->size; + file->attr = info->attribute; file->cacheoffset = -1; file->fileoffset = 0; diff --git a/firmware/common/filefuncs.c b/firmware/common/filefuncs.c index 6eb2bafa40..fd33f3c6f9 100644 --- a/firmware/common/filefuncs.c +++ b/firmware/common/filefuncs.c @@ -70,7 +70,7 @@ bool file_exists(const char *file) #ifdef HAVE_DIRCACHE if (dircache_is_enabled()) - return (dircache_get_entry_ptr(file) != NULL); + return (dircache_get_entry_id(file) >= 0); #endif fd = open(file, O_RDONLY); -- cgit v1.2.3