diff options
Diffstat (limited to 'firmware/common/dir.c')
-rw-r--r-- | firmware/common/dir.c | 93 |
1 files changed, 12 insertions, 81 deletions
diff --git a/firmware/common/dir.c b/firmware/common/dir.c index 245947b134..45749b8474 100644 --- a/firmware/common/dir.c +++ b/firmware/common/dir.c | |||
@@ -28,17 +28,14 @@ | |||
28 | #include "pathfuncs.h" | 28 | #include "pathfuncs.h" |
29 | #include "timefuncs.h" | 29 | #include "timefuncs.h" |
30 | #include "fileobj_mgr.h" | 30 | #include "fileobj_mgr.h" |
31 | #include "dircache_redirect.h" | 31 | #include "rb_namespace.h" |
32 | 32 | ||
33 | /* structure used for open directory streams */ | 33 | /* structure used for open directory streams */ |
34 | static struct dirstr_desc | 34 | static struct dirstr_desc |
35 | { | 35 | { |
36 | struct filestr_base stream; /* basic stream info (first!) */ | 36 | struct filestr_base stream; /* basic stream info (first!) */ |
37 | struct dirscan_info scan; /* directory scan cursor */ | 37 | struct ns_scan_info scan; /* directory scan cursor */ |
38 | struct dirent entry; /* current parsed entry information */ | 38 | struct dirent entry; /* current parsed entry information */ |
39 | #ifdef HAVE_MULTIVOLUME | ||
40 | int volumecounter; /* counter for root volume entries */ | ||
41 | #endif | ||
42 | } open_streams[MAX_OPEN_DIRS]; | 39 | } open_streams[MAX_OPEN_DIRS]; |
43 | 40 | ||
44 | /* check and return a struct dirstr_desc* from a DIR* */ | 41 | /* check and return a struct dirstr_desc* from a DIR* */ |
@@ -48,7 +45,7 @@ static struct dirstr_desc * get_dirstr(DIR *dirp) | |||
48 | 45 | ||
49 | if (!PTR_IN_ARRAY(open_streams, dir, MAX_OPEN_DIRS)) | 46 | if (!PTR_IN_ARRAY(open_streams, dir, MAX_OPEN_DIRS)) |
50 | dir = NULL; | 47 | dir = NULL; |
51 | else if (dir->stream.flags & FDO_BUSY) | 48 | else if (dir->stream.flags & (FDO_BUSY|FD_VALID)) |
52 | return dir; | 49 | return dir; |
53 | 50 | ||
54 | int errnum; | 51 | int errnum; |
@@ -105,50 +102,6 @@ static struct dirstr_desc * alloc_dirstr(void) | |||
105 | return NULL; | 102 | return NULL; |
106 | } | 103 | } |
107 | 104 | ||
108 | #ifdef HAVE_MULTIVOLUME | ||
109 | static int readdir_volume_inner(struct dirstr_desc *dir, struct dirent *entry) | ||
110 | { | ||
111 | /* Volumes (secondary file systems) get inserted into the system root | ||
112 | * directory. If the path specified volume 0, enumeration will not | ||
113 | * include other volumes, but just its own files and directories. | ||
114 | * | ||
115 | * Fake special directories, which don't really exist, that will get | ||
116 | * redirected upon opendir() | ||
117 | */ | ||
118 | while (++dir->volumecounter < NUM_VOLUMES) | ||
119 | { | ||
120 | /* on the system root */ | ||
121 | if (!fat_ismounted(dir->volumecounter)) | ||
122 | continue; | ||
123 | |||
124 | get_volume_name(dir->volumecounter, entry->d_name); | ||
125 | dir->entry.info.attr = ATTR_MOUNT_POINT; | ||
126 | dir->entry.info.size = 0; | ||
127 | dir->entry.info.wrtdate = 0; | ||
128 | dir->entry.info.wrttime = 0; | ||
129 | return 1; | ||
130 | } | ||
131 | |||
132 | /* do normal directory entry fetching */ | ||
133 | return 0; | ||
134 | } | ||
135 | #endif /* HAVE_MULTIVOLUME */ | ||
136 | |||
137 | static inline int readdir_volume(struct dirstr_desc *dir, | ||
138 | struct dirent *entry) | ||
139 | { | ||
140 | #ifdef HAVE_MULTIVOLUME | ||
141 | /* fetch virtual volume entries? */ | ||
142 | if (dir->volumecounter < NUM_VOLUMES) | ||
143 | return readdir_volume_inner(dir, entry); | ||
144 | #endif /* HAVE_MULTIVOLUME */ | ||
145 | |||
146 | /* do normal directory entry fetching */ | ||
147 | return 0; | ||
148 | (void)dir; (void)entry; | ||
149 | } | ||
150 | |||
151 | |||
152 | /** POSIX interface **/ | 105 | /** POSIX interface **/ |
153 | 106 | ||
154 | /* open a directory */ | 107 | /* open a directory */ |
@@ -166,21 +119,13 @@ DIR * opendir(const char *dirname) | |||
166 | if (!dir) | 119 | if (!dir) |
167 | FILE_ERROR(EMFILE, RC); | 120 | FILE_ERROR(EMFILE, RC); |
168 | 121 | ||
169 | rc = open_stream_internal(dirname, FF_DIR, &dir->stream, NULL); | 122 | rc = ns_open_stream(dirname, FF_DIR, &dir->stream, &dir->scan); |
170 | if (rc < 0) | 123 | if (rc < 0) |
171 | { | 124 | { |
172 | DEBUGF("Open failed: %d\n", rc); | 125 | DEBUGF("Open failed: %d\n", rc); |
173 | FILE_ERROR(ERRNO, RC); | 126 | FILE_ERROR(ERRNO, RC); |
174 | } | 127 | } |
175 | 128 | ||
176 | #ifdef HAVE_MULTIVOLUME | ||
177 | /* volume counter is relevant only to the system root */ | ||
178 | dir->volumecounter = rc > 1 ? 0 : INT_MAX; | ||
179 | #endif /* HAVE_MULTIVOLUME */ | ||
180 | |||
181 | fat_rewind(&dir->stream.fatstr); | ||
182 | rewinddir_dirent(&dir->scan); | ||
183 | |||
184 | dirp = (DIR *)dir; | 129 | dirp = (DIR *)dir; |
185 | file_error: | 130 | file_error: |
186 | file_internal_unlock_WRITER(); | 131 | file_internal_unlock_WRITER(); |
@@ -205,7 +150,7 @@ int closedir(DIR *dirp) | |||
205 | FILE_ERROR(EBADF, -2); | 150 | FILE_ERROR(EBADF, -2); |
206 | } | 151 | } |
207 | 152 | ||
208 | rc = close_stream_internal(&dir->stream); | 153 | rc = ns_close_stream(&dir->stream); |
209 | if (rc < 0) | 154 | if (rc < 0) |
210 | FILE_ERROR(ERRNO, rc * 10 - 3); | 155 | FILE_ERROR(ERRNO, rc * 10 - 3); |
211 | 156 | ||
@@ -223,16 +168,11 @@ struct dirent * readdir(DIR *dirp) | |||
223 | 168 | ||
224 | struct dirent *res = NULL; | 169 | struct dirent *res = NULL; |
225 | 170 | ||
226 | int rc = readdir_volume(dir, &dir->entry); | 171 | int rc = ns_readdir_dirent(&dir->stream, &dir->scan, &dir->entry); |
227 | if (rc == 0) | ||
228 | { | ||
229 | rc = readdir_dirent(&dir->stream, &dir->scan, &dir->entry); | ||
230 | if (rc < 0) | ||
231 | FILE_ERROR(EIO, RC); | ||
232 | } | ||
233 | |||
234 | if (rc > 0) | 172 | if (rc > 0) |
235 | res = &dir->entry; | 173 | res = &dir->entry; |
174 | else if (rc < 0) | ||
175 | FILE_ERROR(EIO, RC); | ||
236 | 176 | ||
237 | file_error: | 177 | file_error: |
238 | RELEASE_DIRSTR(READER, dir); | 178 | RELEASE_DIRSTR(READER, dir); |
@@ -259,13 +199,9 @@ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) | |||
259 | if (!dir) | 199 | if (!dir) |
260 | FILE_ERROR_RETURN(ERRNO, -1); | 200 | FILE_ERROR_RETURN(ERRNO, -1); |
261 | 201 | ||
262 | int rc = readdir_volume(dir, entry); | 202 | int rc = ns_readdir_dirent(&dir->stream, &dir->scan, entry); |
263 | if (rc == 0) | 203 | if (rc < 0) |
264 | { | 204 | FILE_ERROR(EIO, rc * 10 - 4); |
265 | rc = readdir_dirent(&dir->stream, &dir->scan, entry); | ||
266 | if (rc < 0) | ||
267 | FILE_ERROR(EIO, rc * 10 - 4); | ||
268 | } | ||
269 | 205 | ||
270 | file_error: | 206 | file_error: |
271 | RELEASE_DIRSTR(READER, dir); | 207 | RELEASE_DIRSTR(READER, dir); |
@@ -289,12 +225,7 @@ void rewinddir(DIR *dirp) | |||
289 | if (!dir) | 225 | if (!dir) |
290 | FILE_ERROR_RETURN(ERRNO); | 226 | FILE_ERROR_RETURN(ERRNO); |
291 | 227 | ||
292 | rewinddir_dirent(&dir->scan); | 228 | ns_dirscan_rewind(&dir->scan); |
293 | |||
294 | #ifdef HAVE_MULTIVOLUME | ||
295 | if (dir->volumecounter != INT_MAX) | ||
296 | dir->volumecounter = 0; | ||
297 | #endif /* HAVE_MULTIVOLUME */ | ||
298 | 229 | ||
299 | RELEASE_DIRSTR(READER, dir); | 230 | RELEASE_DIRSTR(READER, dir); |
300 | } | 231 | } |