summaryrefslogtreecommitdiff
path: root/firmware/common/dir.c
diff options
context:
space:
mode:
authorWilliam Wilgus <me.theuser@yahoo.com>2017-02-03 17:13:58 -0500
committerWilliam Wilgus <me.theuser@yahoo.com>2020-08-20 23:08:57 +0000
commit5ef28cccf92f5eada6d502fa4b0e16a13e94be5b (patch)
tree05f9d2f8bdf3c0cc54c5893159a7dcf07c7e3e55 /firmware/common/dir.c
parent31fc46ded69be7438cca2ba2c2b93c1f200165a6 (diff)
downloadrockbox-5ef28cccf92f5eada6d502fa4b0e16a13e94be5b.tar.gz
rockbox-5ef28cccf92f5eada6d502fa4b0e16a13e94be5b.zip
Allow mounting of any directory as the root directory.
Provide definitions for the macros: * RB_ROOT_VOL_HIDDEN(v) to exclude certain items from the root. * RB_ROOT_CONTENTS to return a string with the name of the directory to mount in the root. Defaults are in export/rbpaths.h It's a bit much for those that don't need the full functionality. Some conditional define can cut it back a lot to cut out things only needed if alternate root mounts are required. I'm just not bothering yet. The basic concept would be applied to all targets to keep file code from forking too much. Change-Id: I90b5c0a1c949283d3102c16734b0b6ac73901a30
Diffstat (limited to 'firmware/common/dir.c')
-rw-r--r--firmware/common/dir.c92
1 files changed, 12 insertions, 80 deletions
diff --git a/firmware/common/dir.c b/firmware/common/dir.c
index f89129ae34..85e6ff316b 100644
--- a/firmware/common/dir.c
+++ b/firmware/common/dir.c
@@ -27,17 +27,14 @@
27#include "dir.h" 27#include "dir.h"
28#include "pathfuncs.h" 28#include "pathfuncs.h"
29#include "fileobj_mgr.h" 29#include "fileobj_mgr.h"
30#include "dircache_redirect.h" 30#include "rb_namespace.h"
31 31
32/* structure used for open directory streams */ 32/* structure used for open directory streams */
33static struct dirstr_desc 33static struct dirstr_desc
34{ 34{
35 struct filestr_base stream; /* basic stream info (first!) */ 35 struct filestr_base stream; /* basic stream info (first!) */
36 struct dirscan_info scan; /* directory scan cursor */ 36 struct ns_scan_info scan; /* directory scan cursor */
37 struct dirent entry; /* current parsed entry information */ 37 struct dirent entry; /* current parsed entry information */
38#ifdef HAVE_MULTIVOLUME
39 int volumecounter; /* counter for root volume entries */
40#endif
41} open_streams[MAX_OPEN_DIRS]; 38} open_streams[MAX_OPEN_DIRS];
42 39
43/* check and return a struct dirstr_desc* from a DIR* */ 40/* check and return a struct dirstr_desc* from a DIR* */
@@ -47,7 +44,7 @@ static struct dirstr_desc * get_dirstr(DIR *dirp)
47 44
48 if (!PTR_IN_ARRAY(open_streams, dir, MAX_OPEN_DIRS)) 45 if (!PTR_IN_ARRAY(open_streams, dir, MAX_OPEN_DIRS))
49 dir = NULL; 46 dir = NULL;
50 else if (dir->stream.flags & FDO_BUSY) 47 else if (dir->stream.flags & (FDO_BUSY|FD_VALID))
51 return dir; 48 return dir;
52 49
53 int errnum; 50 int errnum;
@@ -104,49 +101,6 @@ static struct dirstr_desc * alloc_dirstr(void)
104 return NULL; 101 return NULL;
105} 102}
106 103
107#ifdef HAVE_MULTIVOLUME
108static int readdir_volume_inner(struct dirstr_desc *dir, struct dirent *entry)
109{
110 /* Volumes (secondary file systems) get inserted into the system root
111 * directory. If the path specified volume 0, enumeration will not
112 * include other volumes, but just its own files and directories.
113 *
114 * Fake special directories, which don't really exist, that will get
115 * redirected upon opendir()
116 */
117 while (++dir->volumecounter < NUM_VOLUMES)
118 {
119 /* on the system root */
120 if (!fat_ismounted(dir->volumecounter))
121 continue;
122
123 get_volume_name(dir->volumecounter, entry->d_name);
124 dir->entry.info.attr = ATTR_MOUNT_POINT;
125 dir->entry.info.size = 0;
126 dir->entry.info.wrtdate = 0;
127 dir->entry.info.wrttime = 0;
128 return 1;
129 }
130
131 /* do normal directory entry fetching */
132 return 0;
133}
134#endif /* HAVE_MULTIVOLUME */
135
136static inline int readdir_volume(struct dirstr_desc *dir,
137 struct dirent *entry)
138{
139#ifdef HAVE_MULTIVOLUME
140 /* fetch virtual volume entries? */
141 if (dir->volumecounter < NUM_VOLUMES)
142 return readdir_volume_inner(dir, entry);
143#endif /* HAVE_MULTIVOLUME */
144
145 /* do normal directory entry fetching */
146 return 0;
147 (void)dir; (void)entry;
148}
149
150 104
151/** POSIX interface **/ 105/** POSIX interface **/
152 106
@@ -165,21 +119,13 @@ DIR * opendir(const char *dirname)
165 if (!dir) 119 if (!dir)
166 FILE_ERROR(EMFILE, RC); 120 FILE_ERROR(EMFILE, RC);
167 121
168 rc = open_stream_internal(dirname, FF_DIR, &dir->stream, NULL); 122 rc = ns_open_stream(dirname, FF_DIR, &dir->stream, &dir->scan);
169 if (rc < 0) 123 if (rc < 0)
170 { 124 {
171 DEBUGF("Open failed: %d\n", rc); 125 DEBUGF("Open failed: %d\n", rc);
172 FILE_ERROR(ERRNO, RC); 126 FILE_ERROR(ERRNO, RC);
173 } 127 }
174 128
175#ifdef HAVE_MULTIVOLUME
176 /* volume counter is relevant only to the system root */
177 dir->volumecounter = rc > 1 ? 0 : INT_MAX;
178#endif /* HAVE_MULTIVOLUME */
179
180 fat_rewind(&dir->stream.fatstr);
181 rewinddir_dirent(&dir->scan);
182
183 dirp = (DIR *)dir; 129 dirp = (DIR *)dir;
184file_error: 130file_error:
185 file_internal_unlock_WRITER(); 131 file_internal_unlock_WRITER();
@@ -204,7 +150,7 @@ int closedir(DIR *dirp)
204 FILE_ERROR(EBADF, -2); 150 FILE_ERROR(EBADF, -2);
205 } 151 }
206 152
207 rc = close_stream_internal(&dir->stream); 153 rc = ns_close_stream(&dir->stream);
208 if (rc < 0) 154 if (rc < 0)
209 FILE_ERROR(ERRNO, rc * 10 - 3); 155 FILE_ERROR(ERRNO, rc * 10 - 3);
210 156
@@ -222,16 +168,11 @@ struct dirent * readdir(DIR *dirp)
222 168
223 struct dirent *res = NULL; 169 struct dirent *res = NULL;
224 170
225 int rc = readdir_volume(dir, &dir->entry); 171 int rc = ns_readdir_dirent(&dir->stream, &dir->scan, &dir->entry);
226 if (rc == 0)
227 {
228 rc = readdir_dirent(&dir->stream, &dir->scan, &dir->entry);
229 if (rc < 0)
230 FILE_ERROR(EIO, RC);
231 }
232
233 if (rc > 0) 172 if (rc > 0)
234 res = &dir->entry; 173 res = &dir->entry;
174 else if (rc < 0)
175 FILE_ERROR(EIO, RC);
235 176
236file_error: 177file_error:
237 RELEASE_DIRSTR(READER, dir); 178 RELEASE_DIRSTR(READER, dir);
@@ -258,13 +199,9 @@ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
258 if (!dir) 199 if (!dir)
259 FILE_ERROR_RETURN(ERRNO, -1); 200 FILE_ERROR_RETURN(ERRNO, -1);
260 201
261 int rc = readdir_volume(dir, entry); 202 int rc = ns_readdir_dirent(&dir->stream, &dir->scan, entry);
262 if (rc == 0) 203 if (rc < 0)
263 { 204 FILE_ERROR(EIO, rc * 10 - 4);
264 rc = readdir_dirent(&dir->stream, &dir->scan, entry);
265 if (rc < 0)
266 FILE_ERROR(EIO, rc * 10 - 4);
267 }
268 205
269file_error: 206file_error:
270 RELEASE_DIRSTR(READER, dir); 207 RELEASE_DIRSTR(READER, dir);
@@ -288,12 +225,7 @@ void rewinddir(DIR *dirp)
288 if (!dir) 225 if (!dir)
289 FILE_ERROR_RETURN(ERRNO); 226 FILE_ERROR_RETURN(ERRNO);
290 227
291 rewinddir_dirent(&dir->scan); 228 ns_dirscan_rewind(&dir->scan);
292
293#ifdef HAVE_MULTIVOLUME
294 if (dir->volumecounter != INT_MAX)
295 dir->volumecounter = 0;
296#endif /* HAVE_MULTIVOLUME */
297 229
298 RELEASE_DIRSTR(READER, dir); 230 RELEASE_DIRSTR(READER, dir);
299} 231}