diff options
Diffstat (limited to 'firmware/common')
-rw-r--r-- | firmware/common/dircache.c | 73 | ||||
-rw-r--r-- | firmware/common/file.c | 13 | ||||
-rw-r--r-- | firmware/common/filefuncs.c | 2 |
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 |
60 | static DIR_CACHED opendirs[MAX_OPEN_DIRS]; | 60 | |
61 | #define MAX_PENDING_BINDINGS 2 | ||
62 | struct fdbind_queue { | ||
63 | char path[MAX_PATH]; | ||
64 | int fd; | ||
65 | }; | ||
66 | |||
67 | /* Exported structures. */ | ||
68 | struct 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 | */ |
78 | static 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 */ |
80 | static struct dircache_entry *dircache_root; | 95 | static 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; | |||
86 | static struct dircache_entry *append_position; | 101 | static struct dircache_entry *append_position; |
87 | #endif | 102 | #endif |
88 | 103 | ||
104 | static DIR_CACHED opendirs[MAX_OPEN_DIRS]; | ||
105 | static struct dircache_entry *fd_bindings[MAX_OPEN_FILES]; | ||
106 | |||
89 | static bool dircache_initialized = false; | 107 | static bool dircache_initialized = false; |
90 | static bool dircache_initializing = false; | 108 | static bool dircache_initializing = false; |
91 | static bool thread_enabled = false; | 109 | static 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 | ||
126 | static 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 | */ |
1017 | const struct dircache_entry *dircache_get_entry_ptr(const char *filename) | 1040 | static 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 | |||
1049 | int 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 | */ | ||
1057 | long _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 | */ | ||
1065 | struct 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 | */ |
1053 | size_t dircache_copy_path(const struct dircache_entry *entry, char *buf, size_t size) | 1098 | size_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 | ||
1395 | struct dirent_cached* readdir_cached(DIR_CACHED* dir) | 1440 | struct 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); |