summaryrefslogtreecommitdiff
path: root/firmware/common/dir.c
diff options
context:
space:
mode:
authorWilliam Wilgus <wilgus.william@gmail.com>2022-03-03 07:37:03 -0500
committerWilliam Wilgus <wilgus.william@gmail.com>2022-03-03 18:58:07 -0500
commit9daacabd658508d2607a64b288c9bce7a635fb15 (patch)
treece96538ea82a4176f00f8eb9531711db7dea5750 /firmware/common/dir.c
parentf88ea12bacf381ad4f39ba2328c806e772c0dda8 (diff)
downloadrockbox-9daacabd658508d2607a64b288c9bce7a635fb15.tar.gz
rockbox-9daacabd658508d2607a64b288c9bce7a635fb15.zip
[RESTORED!] 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: I3b5a14c530ff4b10d97f67636237d96875eb8969 Author: Michael Sevakis
Diffstat (limited to 'firmware/common/dir.c')
-rw-r--r--firmware/common/dir.c93
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 */
34static struct dirstr_desc 34static 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
109static 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
137static 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;
185file_error: 130file_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
237file_error: 177file_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
270file_error: 206file_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}