summaryrefslogtreecommitdiff
path: root/firmware/common/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/common/dir.c')
-rw-r--r--firmware/common/dir.c83
1 files changed, 77 insertions, 6 deletions
diff --git a/firmware/common/dir.c b/firmware/common/dir.c
index 1bad9327f6..5fa5f9db6e 100644
--- a/firmware/common/dir.c
+++ b/firmware/common/dir.c
@@ -23,11 +23,48 @@
23#include "fat.h" 23#include "fat.h"
24#include "dir.h" 24#include "dir.h"
25#include "debug.h" 25#include "debug.h"
26#include "atoi.h"
26 27
27#define MAX_OPEN_DIRS 8 28#define MAX_OPEN_DIRS 8
28 29
29static DIR opendirs[MAX_OPEN_DIRS]; 30static DIR opendirs[MAX_OPEN_DIRS];
30 31
32#ifdef HAVE_MULTIVOLUME
33
34/* how to name volumes, first char must be outside of legal file names,
35 a number gets appended to enumerate, if applicable */
36#ifdef HAVE_MMC
37static const char* vol_names = ":MMC";
38#else
39static const char* vol_names = ":HD";
40#endif
41
42/* returns on which volume this is, and copies the reduced name
43 (sortof a preprocessor for volume-decorated pathnames) */
44static int strip_volume(const char* name, char* namecopy)
45{
46 int volume = 0;
47
48 if (name[1] == vol_names[0] ) /* a colon identifies our volumes */
49 {
50 const char* temp;
51 temp = name + 1 + strlen(vol_names); /* behind special name */
52 volume = atoi(temp); /* number is following */
53 temp = strchr(temp, '/'); /* search for slash behind */
54 if (temp != NULL)
55 name = temp; /* use the part behind the volume */
56 else
57 name = "/"; /* else this must be the root dir */
58 }
59
60 strncpy(namecopy, name, MAX_PATH);
61 namecopy[MAX_PATH-1] = '\0';
62
63 return volume;
64}
65#endif /* #ifdef HAVE_MULTIVOLUME */
66
67
31DIR* opendir(const char* name) 68DIR* opendir(const char* name)
32{ 69{
33 char namecopy[MAX_PATH]; 70 char namecopy[MAX_PATH];
@@ -35,6 +72,9 @@ DIR* opendir(const char* name)
35 char* end; 72 char* end;
36 struct fat_direntry entry; 73 struct fat_direntry entry;
37 int dd; 74 int dd;
75#ifdef HAVE_MULTIVOLUME
76 int volume;
77#endif
38 78
39 /* find a free dir descriptor */ 79 /* find a free dir descriptor */
40 for ( dd=0; dd<MAX_OPEN_DIRS; dd++ ) 80 for ( dd=0; dd<MAX_OPEN_DIRS; dd++ )
@@ -55,15 +95,21 @@ DIR* opendir(const char* name)
55 return NULL; 95 return NULL;
56 } 96 }
57 97
58 if ( fat_opendir(&(opendirs[dd].fatdir), 0, NULL) < 0 ) { 98#ifdef HAVE_MULTIVOLUME
99 /* try to extract a heading volume name, if present */
100 volume = strip_volume(name, namecopy);
101 opendirs[dd].volumecounter = 0;
102#else
103 strncpy(namecopy,name,sizeof(namecopy)); /* just copy */
104 namecopy[sizeof(namecopy)-1] = '\0';
105#endif
106
107 if ( fat_opendir(IF_MV2(volume,) &(opendirs[dd].fatdir), 0, NULL) < 0 ) {
59 DEBUGF("Failed opening root dir\n"); 108 DEBUGF("Failed opening root dir\n");
60 opendirs[dd].busy = false; 109 opendirs[dd].busy = false;
61 return NULL; 110 return NULL;
62 } 111 }
63 112
64 strncpy(namecopy,name,sizeof(namecopy));
65 namecopy[sizeof(namecopy)-1] = 0;
66
67 for ( part = strtok_r(namecopy, "/", &end); part; 113 for ( part = strtok_r(namecopy, "/", &end); part;
68 part = strtok_r(NULL, "/", &end)) { 114 part = strtok_r(NULL, "/", &end)) {
69 /* scan dir for name */ 115 /* scan dir for name */
@@ -76,7 +122,8 @@ DIR* opendir(const char* name)
76 if ( (entry.attr & FAT_ATTR_DIRECTORY) && 122 if ( (entry.attr & FAT_ATTR_DIRECTORY) &&
77 (!strcasecmp(part, entry.name)) ) { 123 (!strcasecmp(part, entry.name)) ) {
78 opendirs[dd].parent_dir = opendirs[dd].fatdir; 124 opendirs[dd].parent_dir = opendirs[dd].fatdir;
79 if ( fat_opendir(&(opendirs[dd].fatdir), 125 if ( fat_opendir(IF_MV2(volume,)
126 &(opendirs[dd].fatdir),
80 entry.firstcluster, 127 entry.firstcluster,
81 &(opendirs[dd].parent_dir)) < 0 ) { 128 &(opendirs[dd].parent_dir)) < 0 ) {
82 DEBUGF("Failed opening dir '%s' (%d)\n", 129 DEBUGF("Failed opening dir '%s' (%d)\n",
@@ -84,6 +131,9 @@ DIR* opendir(const char* name)
84 opendirs[dd].busy = false; 131 opendirs[dd].busy = false;
85 return NULL; 132 return NULL;
86 } 133 }
134#ifdef HAVE_MULTIVOLUME
135 opendirs[dd].volumecounter = -1; /* n.a. to subdirs */
136#endif
87 break; 137 break;
88 } 138 }
89 } 139 }
@@ -102,7 +152,28 @@ struct dirent* readdir(DIR* dir)
102{ 152{
103 struct fat_direntry entry; 153 struct fat_direntry entry;
104 struct dirent* theent = &(dir->theent); 154 struct dirent* theent = &(dir->theent);
105 155#ifdef HAVE_MULTIVOLUME
156 /* Volumes (secondary file systems) get inserted into the root directory
157 of the first volume, since we have no separate top level. */
158 if (dir->volumecounter >= 0 /* on a root dir */
159 && dir->volumecounter < NUM_VOLUMES /* in range */
160 && dir->fatdir.file.volume == 0) /* at volume 0 */
161 { /* fake special directories, which don't really exist, but
162 will get redirected upon opendir() */
163 while (++dir->volumecounter < NUM_VOLUMES)
164 {
165 if (fat_ismounted(dir->volumecounter))
166 {
167 memset(theent, 0, sizeof(*theent));
168 theent->attribute = FAT_ATTR_DIRECTORY | FAT_ATTR_VOLUME;
169 snprintf(theent->d_name, sizeof(theent->d_name),
170 "%s%d", vol_names, dir->volumecounter);
171 return theent;
172 }
173 }
174 }
175#endif
176 /* normal directory entry fetching follows here */
106 if (fat_getnext(&(dir->fatdir),&entry) < 0) 177 if (fat_getnext(&(dir->fatdir),&entry) < 0)
107 return NULL; 178 return NULL;
108 179