diff options
-rw-r--r-- | firmware/common/dircache.c | 95 | ||||
-rw-r--r-- | firmware/include/dir.h | 2 | ||||
-rw-r--r-- | firmware/include/dircache.h | 17 |
3 files changed, 61 insertions, 53 deletions
diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c index e6107801c3..078836147e 100644 --- a/firmware/common/dircache.c +++ b/firmware/common/dircache.c | |||
@@ -73,7 +73,7 @@ static unsigned int cache_build_ticks = 0; | |||
73 | static unsigned long appflags = 0; | 73 | static unsigned long appflags = 0; |
74 | 74 | ||
75 | static struct event_queue dircache_queue; | 75 | static struct event_queue dircache_queue; |
76 | static long dircache_stack[(DEFAULT_STACK_SIZE + 0x900)/sizeof(long)]; | 76 | static long dircache_stack[(DEFAULT_STACK_SIZE + 0x200)/sizeof(long)]; |
77 | static const char dircache_thread_name[] = "dircache"; | 77 | static const char dircache_thread_name[] = "dircache"; |
78 | 78 | ||
79 | static struct fdbind_queue fdbind_cache[MAX_PENDING_BINDINGS]; | 79 | static struct fdbind_queue fdbind_cache[MAX_PENDING_BINDINGS]; |
@@ -270,6 +270,9 @@ static int sab_process_dir(unsigned long startcluster, struct dircache_entry *ce | |||
270 | return rc; | 270 | return rc; |
271 | } | 271 | } |
272 | 272 | ||
273 | /* used during the generation */ | ||
274 | static struct fat_dir sab_fat_dir; | ||
275 | |||
273 | static int dircache_scan_and_build(IF_MV2(int volume,) struct dircache_entry *ce) | 276 | static int dircache_scan_and_build(IF_MV2(int volume,) struct dircache_entry *ce) |
274 | { | 277 | { |
275 | memset(ce, 0, sizeof(struct dircache_entry)); | 278 | memset(ce, 0, sizeof(struct dircache_entry)); |
@@ -288,12 +291,11 @@ static int dircache_scan_and_build(IF_MV2(int volume,) struct dircache_entry *ce | |||
288 | } | 291 | } |
289 | #endif | 292 | #endif |
290 | 293 | ||
291 | struct fat_dir dir; /* allocate on stack once for all scan */ | ||
292 | struct fat_direntry direntry; /* ditto */ | 294 | struct fat_direntry direntry; /* ditto */ |
293 | #ifdef HAVE_MULTIVOLUME | 295 | #ifdef HAVE_MULTIVOLUME |
294 | sab.volume = volume; | 296 | sab.volume = volume; |
295 | #endif | 297 | #endif |
296 | sab.dir = &dir; | 298 | sab.dir = &sab_fat_dir; |
297 | sab.direntry = &direntry; | 299 | sab.direntry = &direntry; |
298 | 300 | ||
299 | return sab_process_dir(0, ce); | 301 | return sab_process_dir(0, ce); |
@@ -615,7 +617,7 @@ static int dircache_do_rebuild(void) | |||
615 | if (dircache_scan_and_build(IF_MV2(0,) dircache_root) < 0) | 617 | if (dircache_scan_and_build(IF_MV2(0,) dircache_root) < 0) |
616 | #endif /* HAVE_MULTIVOLUME */ | 618 | #endif /* HAVE_MULTIVOLUME */ |
617 | { | 619 | { |
618 | logf("dircache_travel failed"); | 620 | logf("dircache_scan_and_build failed"); |
619 | cpu_boost(false); | 621 | cpu_boost(false); |
620 | dircache_size = 0; | 622 | dircache_size = 0; |
621 | dircache_initializing = false; | 623 | dircache_initializing = false; |
@@ -765,7 +767,7 @@ void dircache_init(void) | |||
765 | memset(opendirs, 0, sizeof(opendirs)); | 767 | memset(opendirs, 0, sizeof(opendirs)); |
766 | for (i = 0; i < MAX_OPEN_DIRS; i++) | 768 | for (i = 0; i < MAX_OPEN_DIRS; i++) |
767 | { | 769 | { |
768 | opendirs[i].secondary_entry.d_name = buffer_alloc(MAX_PATH); | 770 | opendirs[i].theent.d_name = buffer_alloc(MAX_PATH); |
769 | } | 771 | } |
770 | 772 | ||
771 | queue_init(&dircache_queue, true); | 773 | queue_init(&dircache_queue, true); |
@@ -1205,7 +1207,6 @@ void dircache_add_file(const char *path, long startcluster) | |||
1205 | 1207 | ||
1206 | DIR_CACHED* opendir_cached(const char* name) | 1208 | DIR_CACHED* opendir_cached(const char* name) |
1207 | { | 1209 | { |
1208 | struct dircache_entry *cache_entry; | ||
1209 | int dd; | 1210 | int dd; |
1210 | DIR_CACHED* pdir = opendirs; | 1211 | DIR_CACHED* pdir = opendirs; |
1211 | 1212 | ||
@@ -1226,23 +1227,22 @@ DIR_CACHED* opendir_cached(const char* name) | |||
1226 | errno = EMFILE; | 1227 | errno = EMFILE; |
1227 | return NULL; | 1228 | return NULL; |
1228 | } | 1229 | } |
1230 | |||
1231 | pdir->busy = true; | ||
1229 | 1232 | ||
1230 | if (!dircache_initialized) | 1233 | if (!dircache_initialized) |
1231 | { | 1234 | { |
1232 | pdir->regulardir = opendir_uncached(name); | 1235 | pdir->internal_entry = NULL; |
1233 | if (!pdir->regulardir) | 1236 | pdir->regulardir = opendir_uncached(name); |
1234 | return NULL; | 1237 | } |
1235 | 1238 | else | |
1236 | pdir->busy = true; | 1239 | { |
1237 | return pdir; | 1240 | pdir->regulardir = NULL; |
1241 | pdir->internal_entry = dircache_get_entry(name, true); | ||
1242 | pdir->theent.attribute = -1; /* used to make readdir_cached aware of the first call */ | ||
1238 | } | 1243 | } |
1239 | |||
1240 | pdir->busy = true; | ||
1241 | pdir->regulardir = NULL; | ||
1242 | cache_entry = dircache_get_entry(name, true); | ||
1243 | pdir->entry = cache_entry; | ||
1244 | 1244 | ||
1245 | if (cache_entry == NULL) | 1245 | if (pdir->internal_entry == NULL && pdir->regulardir == NULL) |
1246 | { | 1246 | { |
1247 | pdir->busy = false; | 1247 | pdir->busy = false; |
1248 | return NULL; | 1248 | return NULL; |
@@ -1251,10 +1251,10 @@ DIR_CACHED* opendir_cached(const char* name) | |||
1251 | return pdir; | 1251 | return pdir; |
1252 | } | 1252 | } |
1253 | 1253 | ||
1254 | struct dircache_entry* readdir_cached(DIR_CACHED* dir) | 1254 | struct dirent_cached* readdir_cached(DIR_CACHED* dir) |
1255 | { | 1255 | { |
1256 | struct dircache_entry *ce = dir->internal_entry; | ||
1256 | struct dirent_uncached *regentry; | 1257 | struct dirent_uncached *regentry; |
1257 | struct dircache_entry *ce; | ||
1258 | 1258 | ||
1259 | if (!dir->busy) | 1259 | if (!dir->busy) |
1260 | return NULL; | 1260 | return NULL; |
@@ -1265,41 +1265,40 @@ struct dircache_entry* readdir_cached(DIR_CACHED* dir) | |||
1265 | if (regentry == NULL) | 1265 | if (regentry == NULL) |
1266 | return NULL; | 1266 | return NULL; |
1267 | 1267 | ||
1268 | strlcpy(dir->secondary_entry.d_name, regentry->d_name, MAX_PATH); | 1268 | strlcpy(dir->theent.d_name, regentry->d_name, MAX_PATH); |
1269 | dir->secondary_entry.size = regentry->size; | 1269 | dir->theent.size = regentry->size; |
1270 | dir->secondary_entry.startcluster = regentry->startcluster; | 1270 | dir->theent.startcluster = regentry->startcluster; |
1271 | dir->secondary_entry.attribute = regentry->attribute; | 1271 | dir->theent.attribute = regentry->attribute; |
1272 | dir->secondary_entry.wrttime = regentry->wrttime; | 1272 | dir->theent.wrttime = regentry->wrttime; |
1273 | dir->secondary_entry.wrtdate = regentry->wrtdate; | 1273 | dir->theent.wrtdate = regentry->wrtdate; |
1274 | dir->secondary_entry.next = NULL; | ||
1275 | 1274 | ||
1276 | return &dir->secondary_entry; | 1275 | return &dir->theent; |
1277 | } | 1276 | } |
1278 | 1277 | ||
1279 | do { | 1278 | /* if theent.attribute=-1 then this is the first call */ |
1280 | if (dir->entry == NULL) | 1279 | /* otherwise, this is is not so we first take the entry's ->next */ |
1280 | /* NOTE: normal file can't have attribute=-1 */ | ||
1281 | if(dir->theent.attribute != -1) | ||
1282 | ce = ce->next; | ||
1283 | /* skip unused entries */ | ||
1284 | while(ce != NULL && ce->name_len == 0) | ||
1285 | ce = ce->next; | ||
1286 | |||
1287 | if (ce == NULL) | ||
1281 | return NULL; | 1288 | return NULL; |
1282 | 1289 | ||
1283 | ce = dir->entry; | 1290 | strlcpy(dir->theent.d_name, ce->d_name, MAX_PATH); |
1284 | if (ce->name_len == 0) | 1291 | /* Can't do `dir->theent = *ce` |
1285 | dir->entry = ce->next; | ||
1286 | } while (ce->name_len == 0) ; | ||
1287 | |||
1288 | dir->entry = ce->next; | ||
1289 | |||
1290 | strlcpy(dir->secondary_entry.d_name, ce->d_name, MAX_PATH); | ||
1291 | /* Can't do `dir->secondary_entry = *ce` | ||
1292 | because that modifies the d_name pointer. */ | 1292 | because that modifies the d_name pointer. */ |
1293 | dir->secondary_entry.size = ce->size; | 1293 | dir->theent.size = ce->size; |
1294 | dir->secondary_entry.startcluster = ce->startcluster; | 1294 | dir->theent.startcluster = ce->startcluster; |
1295 | dir->secondary_entry.attribute = ce->attribute; | 1295 | dir->theent.attribute = ce->attribute; |
1296 | dir->secondary_entry.wrttime = ce->wrttime; | 1296 | dir->theent.wrttime = ce->wrttime; |
1297 | dir->secondary_entry.wrtdate = ce->wrtdate; | 1297 | dir->theent.wrtdate = ce->wrtdate; |
1298 | dir->secondary_entry.next = NULL; | ||
1299 | dir->internal_entry = ce; | 1298 | dir->internal_entry = ce; |
1300 | 1299 | ||
1301 | //logf("-> %s", ce->name); | 1300 | //logf("-> %s", ce->name); |
1302 | return &dir->secondary_entry; | 1301 | return &dir->theent; |
1303 | } | 1302 | } |
1304 | 1303 | ||
1305 | int closedir_cached(DIR_CACHED* dir) | 1304 | int closedir_cached(DIR_CACHED* dir) |
@@ -1325,7 +1324,7 @@ int mkdir_cached(const char *name) | |||
1325 | int rmdir_cached(const char* name) | 1324 | int rmdir_cached(const char* name) |
1326 | { | 1325 | { |
1327 | int rc=rmdir_uncached(name); | 1326 | int rc=rmdir_uncached(name); |
1328 | if(rc>=0) | 1327 | if(rc >= 0) |
1329 | dircache_rmdir(name); | 1328 | dircache_rmdir(name); |
1330 | return(rc); | 1329 | return(rc); |
1331 | } | 1330 | } |
diff --git a/firmware/include/dir.h b/firmware/include/dir.h index 5aa6cde35a..9ff96e3419 100644 --- a/firmware/include/dir.h +++ b/firmware/include/dir.h | |||
@@ -44,7 +44,7 @@ | |||
44 | #ifdef HAVE_DIRCACHE | 44 | #ifdef HAVE_DIRCACHE |
45 | # include "dircache.h" | 45 | # include "dircache.h" |
46 | # define DIR DIR_CACHED | 46 | # define DIR DIR_CACHED |
47 | # define dirent dircache_entry | 47 | # define dirent dirent_cached |
48 | # define opendir opendir_cached | 48 | # define opendir opendir_cached |
49 | # define closedir closedir_cached | 49 | # define closedir closedir_cached |
50 | # define readdir readdir_cached | 50 | # define readdir readdir_cached |
diff --git a/firmware/include/dircache.h b/firmware/include/dircache.h index b5b1b72c40..0950d0078b 100644 --- a/firmware/include/dircache.h +++ b/firmware/include/dircache.h | |||
@@ -76,11 +76,20 @@ struct dircache_entry { | |||
76 | char *d_name; | 76 | char *d_name; |
77 | }; | 77 | }; |
78 | 78 | ||
79 | struct dirent_cached { | ||
80 | char *d_name; | ||
81 | int attribute; | ||
82 | long size; | ||
83 | long startcluster; | ||
84 | unsigned short wrtdate; /* Last write date */ | ||
85 | unsigned short wrttime; /* Last write time */ | ||
86 | }; | ||
87 | |||
79 | typedef struct { | 88 | typedef struct { |
80 | bool busy; | 89 | bool busy; |
81 | struct dircache_entry *entry; | 90 | struct dirent_cached theent; /* .attribute is set to -1 on init(opendir) */ |
82 | struct dircache_entry *internal_entry; | 91 | /* the two following field can't be used at the same time so have an union */ |
83 | struct dircache_entry secondary_entry; | 92 | struct dircache_entry *internal_entry; /* the current entry in the directory */ |
84 | DIR_UNCACHED *regulardir; | 93 | DIR_UNCACHED *regulardir; |
85 | } DIR_CACHED; | 94 | } DIR_CACHED; |
86 | 95 | ||
@@ -111,7 +120,7 @@ void dircache_rename(const char *oldpath, const char *newpath); | |||
111 | void dircache_add_file(const char *path, long startcluster); | 120 | void dircache_add_file(const char *path, long startcluster); |
112 | 121 | ||
113 | DIR_CACHED* opendir_cached(const char* name); | 122 | DIR_CACHED* opendir_cached(const char* name); |
114 | struct dircache_entry* readdir_cached(DIR_CACHED* dir); | 123 | struct dirent_cached* readdir_cached(DIR_CACHED* dir); |
115 | int closedir_cached(DIR_CACHED *dir); | 124 | int closedir_cached(DIR_CACHED *dir); |
116 | int mkdir_cached(const char *name); | 125 | int mkdir_cached(const char *name); |
117 | int rmdir_cached(const char* name); | 126 | int rmdir_cached(const char* name); |