summaryrefslogtreecommitdiff
path: root/firmware/common
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/common')
-rw-r--r--firmware/common/dircache.c73
-rw-r--r--firmware/common/file.c13
-rw-r--r--firmware/common/filefuncs.c2
3 files changed, 67 insertions, 21 deletions
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 @@
57#else 57#else
58#define MAX_OPEN_DIRS 8 58#define MAX_OPEN_DIRS 8
59#endif 59#endif
60static DIR_CACHED opendirs[MAX_OPEN_DIRS]; 60
61#define MAX_PENDING_BINDINGS 2
62struct fdbind_queue {
63 char path[MAX_PATH];
64 int fd;
65};
66
67/* Exported structures. */
68struct dircache_entry {
69 struct dirinfo info;
70 struct dircache_entry *next;
71 struct dircache_entry *up;
72 struct dircache_entry *down;
73 long startcluster;
74 char *d_name;
75};
76
61/* Cache Layout: 77/* Cache Layout:
62 * 78 *
63 * x - array of struct dircache_entry 79 * x - array of struct dircache_entry
@@ -75,7 +91,6 @@ static DIR_CACHED opendirs[MAX_OPEN_DIRS];
75 * total allocation size grows 91 * total allocation size grows
76 * |xxxxxxxx|rrrrrrrrr|dddddddd| 92 * |xxxxxxxx|rrrrrrrrr|dddddddd|
77 */ 93 */
78static struct dircache_entry *fd_bindings[MAX_OPEN_FILES];
79/* this points to the beginnging of the buffer and the first entry */ 94/* this points to the beginnging of the buffer and the first entry */
80static struct dircache_entry *dircache_root; 95static struct dircache_entry *dircache_root;
81/* these point to the start and end of the name buffer (d above) */ 96/* these point to the start and end of the name buffer (d above) */
@@ -86,6 +101,9 @@ static char *dot, *dotdot;
86static struct dircache_entry *append_position; 101static struct dircache_entry *append_position;
87#endif 102#endif
88 103
104static DIR_CACHED opendirs[MAX_OPEN_DIRS];
105static struct dircache_entry *fd_bindings[MAX_OPEN_FILES];
106
89static bool dircache_initialized = false; 107static bool dircache_initialized = false;
90static bool dircache_initializing = false; 108static bool dircache_initializing = false;
91static bool thread_enabled = false; 109static bool thread_enabled = false;
@@ -105,6 +123,11 @@ static int fdbind_idx = 0;
105 123
106/* --- Internal cache structure control functions --- */ 124/* --- Internal cache structure control functions --- */
107 125
126static inline struct dircache_entry* get_entry(int id)
127{
128 return &dircache_root[id];
129}
130
108#ifdef HAVE_EEPROM_SETTINGS 131#ifdef HAVE_EEPROM_SETTINGS
109/** 132/**
110 * Open the dircache file to save a snapshot on disk 133 * Open the dircache file to save a snapshot on disk
@@ -1012,14 +1035,36 @@ void dircache_disable(void)
1012} 1035}
1013 1036
1014/** 1037/**
1015 * Usermode function to return dircache_entry pointer to the given path. 1038 * Usermode function to return dircache_entry index to the given path.
1016 */ 1039 */
1017const struct dircache_entry *dircache_get_entry_ptr(const char *filename) 1040static int dircache_get_entry_id_ex(const char *filename, bool go_down)
1018{ 1041{
1019 if (!dircache_initialized || filename == NULL) 1042 if (!dircache_initialized || filename == NULL)
1020 return NULL; 1043 return -1;
1021 1044
1022 return dircache_get_entry(filename, false); 1045 struct dircache_entry* res = dircache_get_entry(filename, go_down);
1046 return res ? res - dircache_root : -1;
1047}
1048
1049int dircache_get_entry_id(const char* filename)
1050{
1051 return dircache_get_entry_id_ex(filename, false);
1052}
1053
1054/**
1055 * Internal: Get the startcluster for the index
1056 */
1057long _dircache_get_entry_startcluster(int id)
1058{
1059 return get_entry(id)->startcluster;
1060}
1061
1062/**
1063 * Internal: Get the struct dirinfo for the index
1064 */
1065struct dirinfo* _dircache_get_entry_dirinfo(int id)
1066{
1067 return &get_entry(id)->info;
1023} 1068}
1024 1069
1025/* 1070/*
@@ -1050,13 +1095,13 @@ static size_t copy_path_helper(const struct dircache_entry *entry, char *buf, si
1050 * 1095 *
1051 * Returns the size of the resulting string, or 0 if an error occured 1096 * Returns the size of the resulting string, or 0 if an error occured
1052 */ 1097 */
1053size_t dircache_copy_path(const struct dircache_entry *entry, char *buf, size_t size) 1098size_t dircache_copy_path(int index, char *buf, size_t size)
1054{ 1099{
1055 if (!size || !buf) 1100 if (!size || !buf || index < 0)
1056 return 0; 1101 return 0;
1057 1102
1058 buf[0] = '/'; 1103 buf[0] = '/';
1059 size_t res = copy_path_helper(entry, buf, size); 1104 size_t res = copy_path_helper(&dircache_root[index], buf, size);
1060 /* fixup trailing '/' */ 1105 /* fixup trailing '/' */
1061 buf[res] = '\0'; 1106 buf[res] = '\0';
1062 return res; 1107 return res;
@@ -1373,17 +1418,17 @@ DIR_CACHED* opendir_cached(const char* name)
1373 1418
1374 if (!dircache_initialized || is_disable_msg_pending()) 1419 if (!dircache_initialized || is_disable_msg_pending())
1375 { 1420 {
1376 pdir->internal_entry = NULL; 1421 pdir->internal_entry = -1;
1377 pdir->regulardir = opendir_uncached(name); 1422 pdir->regulardir = opendir_uncached(name);
1378 } 1423 }
1379 else 1424 else
1380 { 1425 {
1381 pdir->regulardir = NULL; 1426 pdir->regulardir = NULL;
1382 pdir->internal_entry = dircache_get_entry(name, true); 1427 pdir->internal_entry = dircache_get_entry_id_ex(name, true);
1383 pdir->theent.info.attribute = -1; /* used to make readdir_cached aware of the first call */ 1428 pdir->theent.info.attribute = -1; /* used to make readdir_cached aware of the first call */
1384 } 1429 }
1385 1430
1386 if (pdir->internal_entry == NULL && pdir->regulardir == NULL) 1431 if (pdir->internal_entry == -1 && pdir->regulardir == NULL)
1387 { 1432 {
1388 pdir->busy = false; 1433 pdir->busy = false;
1389 return NULL; 1434 return NULL;
@@ -1394,7 +1439,7 @@ DIR_CACHED* opendir_cached(const char* name)
1394 1439
1395struct dirent_cached* readdir_cached(DIR_CACHED* dir) 1440struct dirent_cached* readdir_cached(DIR_CACHED* dir)
1396{ 1441{
1397 struct dircache_entry *ce = dir->internal_entry; 1442 struct dircache_entry *ce = get_entry(dir->internal_entry);
1398 struct dirent_uncached *regentry; 1443 struct dirent_uncached *regentry;
1399 1444
1400 if (!dir->busy) 1445 if (!dir->busy)
@@ -1430,7 +1475,7 @@ struct dirent_cached* readdir_cached(DIR_CACHED* dir)
1430 because that modifies the d_name pointer. */ 1475 because that modifies the d_name pointer. */
1431 dir->theent.startcluster = ce->startcluster; 1476 dir->theent.startcluster = ce->startcluster;
1432 dir->theent.info = ce->info; 1477 dir->theent.info = ce->info;
1433 dir->internal_entry = ce; 1478 dir->internal_entry = ce - dircache_root;
1434 1479
1435 //logf("-> %s", ce->d_name); 1480 //logf("-> %s", ce->d_name);
1436 return &dir->theent; 1481 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)
108#ifdef HAVE_DIRCACHE 108#ifdef HAVE_DIRCACHE
109 if (dircache_is_enabled() && !file->write && use_cache) 109 if (dircache_is_enabled() && !file->write && use_cache)
110 { 110 {
111 const struct dircache_entry *ce;
112# ifdef HAVE_MULTIVOLUME 111# ifdef HAVE_MULTIVOLUME
113 int volume = strip_volume(pathname, pathnamecopy); 112 int volume = strip_volume(pathname, pathnamecopy);
114# endif 113# endif
115 114
116 ce = dircache_get_entry_ptr(pathname); 115 int ce = dircache_get_entry_id(pathname);
117 if (!ce) 116 if (ce < 0)
118 { 117 {
119 errno = ENOENT; 118 errno = ENOENT;
120 file->busy = false; 119 file->busy = false;
121 return -7; 120 return -7;
122 } 121 }
123 122
123 long startcluster = _dircache_get_entry_startcluster(ce);
124 fat_open(IF_MV2(volume,) 124 fat_open(IF_MV2(volume,)
125 ce->startcluster, 125 startcluster,
126 &(file->fatfile), 126 &(file->fatfile),
127 NULL); 127 NULL);
128 file->size = ce->info.size; 128 struct dirinfo *info = _dircache_get_entry_dirinfo(ce);
129 file->attr = ce->info.attribute; 129 file->size = info->size;
130 file->attr = info->attribute;
130 file->cacheoffset = -1; 131 file->cacheoffset = -1;
131 file->fileoffset = 0; 132 file->fileoffset = 0;
132 133
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)
70 70
71#ifdef HAVE_DIRCACHE 71#ifdef HAVE_DIRCACHE
72 if (dircache_is_enabled()) 72 if (dircache_is_enabled())
73 return (dircache_get_entry_ptr(file) != NULL); 73 return (dircache_get_entry_id(file) >= 0);
74#endif 74#endif
75 75
76 fd = open(file, O_RDONLY); 76 fd = open(file, O_RDONLY);