summaryrefslogtreecommitdiff
path: root/firmware/common/fileobj_mgr.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/fileobj_mgr.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/fileobj_mgr.c')
-rw-r--r--firmware/common/fileobj_mgr.c103
1 files changed, 76 insertions, 27 deletions
diff --git a/firmware/common/fileobj_mgr.c b/firmware/common/fileobj_mgr.c
index e34a460e10..da82681acc 100644
--- a/firmware/common/fileobj_mgr.c
+++ b/firmware/common/fileobj_mgr.c
@@ -20,12 +20,13 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21#include "config.h" 21#include "config.h"
22#include "system.h" 22#include "system.h"
23#include <errno.h>
23#include "debug.h" 24#include "debug.h"
24#include "file.h" 25#include "file.h"
25#include "dir.h" 26#include "dir.h"
26#include "disk_cache.h" 27#include "disk_cache.h"
27#include "fileobj_mgr.h" 28#include "fileobj_mgr.h"
28#include "dircache_redirect.h" 29#include "rb_namespace.h"
29 30
30/** 31/**
31 * Manages file and directory streams on all volumes 32 * Manages file and directory streams on all volumes
@@ -34,8 +35,8 @@
34 */ 35 */
35 36
36 37
37/* there will always be enough of these for all user handles, thus these 38/* there will always be enough of these for all user handles, thus most of
38 functions don't return failure codes */ 39 these functions don't return failure codes */
39#define MAX_FILEOBJS (MAX_OPEN_HANDLES + AUX_FILEOBJS) 40#define MAX_FILEOBJS (MAX_OPEN_HANDLES + AUX_FILEOBJS)
40 41
41/* describes the file as an image on the storage medium */ 42/* describes the file as an image on the storage medium */
@@ -84,6 +85,14 @@ static struct ll_head busy_bindings[NUM_VOLUMES];
84 for (struct filestr_base *s = STREAM_##what(start); \ 85 for (struct filestr_base *s = STREAM_##what(start); \
85 s; s = STREAM_NEXT(s)) 86 s; s = STREAM_NEXT(s))
86 87
88/* once a file/directory, always a file/directory; such a change
89 is a bug */
90#define CHECK_FO_DIRECTORY(callflags, fobp) \
91 if (((callflags) ^ (fobp)->flags) & FO_DIRECTORY) \
92 { \
93 DEBUGF("%s - FO_DIRECTORY flag does not match: %p %u\n", \
94 __func__, (fobp), (callflags)); \
95 }
87 96
88/* syncs information for the stream's old and new parent directory if any are 97/* syncs information for the stream's old and new parent directory if any are
89 currently opened */ 98 currently opened */
@@ -96,6 +105,9 @@ static void fileobj_sync_parent(const struct file_base_info *infop[],
96 continue; /* not directory or removed can't be parent of anything */ 105 continue; /* not directory or removed can't be parent of anything */
97 106
98 struct filestr_base *parentstrp = STREAM_FIRST(fobp); 107 struct filestr_base *parentstrp = STREAM_FIRST(fobp);
108 if (!parentstrp)
109 continue;
110
99 struct fat_file *parentfilep = &parentstrp->infop->fatfile; 111 struct fat_file *parentfilep = &parentstrp->infop->fatfile;
100 112
101 for (int i = 0; i < count; i++) 113 for (int i = 0; i < count; i++)
@@ -111,8 +123,8 @@ static void fileobj_sync_parent(const struct file_base_info *infop[],
111} 123}
112 124
113/* see if this file has open streams and return that fileobj_binding if so, 125/* see if this file has open streams and return that fileobj_binding if so,
114 else grab a new one from the free list; returns true if this stream is 126 else grab a new one from the free list; returns true if this is new */
115 the only open one */ 127
116static bool binding_assign(const struct file_base_info *srcinfop, 128static bool binding_assign(const struct file_base_info *srcinfop,
117 struct fileobj_binding **fobpp) 129 struct fileobj_binding **fobpp)
118{ 130{
@@ -123,7 +135,7 @@ static bool binding_assign(const struct file_base_info *srcinfop,
123 135
124 if (fat_file_is_same(&srcinfop->fatfile, &fobp->bind.info.fatfile)) 136 if (fat_file_is_same(&srcinfop->fatfile, &fobp->bind.info.fatfile))
125 { 137 {
126 /* already has open streams */ 138 /* already has open streams/mounts*/
127 *fobpp = fobp; 139 *fobpp = fobp;
128 return false; 140 return false;
129 } 141 }
@@ -143,6 +155,22 @@ static void binding_add_to_free_list(struct fileobj_binding *fobp)
143 ll_insert_last(FREE_BINDINGS(), &fobp->bind.node); 155 ll_insert_last(FREE_BINDINGS(), &fobp->bind.node);
144} 156}
145 157
158static void bind_source_info(const struct file_base_info *srcinfop,
159 struct fileobj_binding **fobpp)
160{
161 if (!binding_assign(srcinfop, fobpp))
162 return; /* already in use */
163 /* is new */
164 (*fobpp)->bind.info = *srcinfop;
165 fileobj_bind_file(&(*fobpp)->bind);
166}
167
168static void release_binding(struct fileobj_binding *fobp)
169{
170 fileobj_unbind_file(&fobp->bind);
171 binding_add_to_free_list(fobp);
172}
173
146/** File and directory internal interface **/ 174/** File and directory internal interface **/
147 175
148void file_binding_insert_last(struct file_base_binding *bindp) 176void file_binding_insert_last(struct file_base_binding *bindp)
@@ -169,6 +197,33 @@ void file_binding_remove_next(struct file_base_binding *prevp,
169} 197}
170#endif /* HAVE_DIRCACHE */ 198#endif /* HAVE_DIRCACHE */
171 199
200/* mounts a file object as a target from elsewhere */
201bool fileobj_mount(const struct file_base_info *srcinfop,
202 unsigned int callflags,
203 struct file_base_binding **bindpp)
204{
205 struct fileobj_binding *fobp;
206 bind_source_info(srcinfop, &fobp);
207 CHECK_FO_DIRECTORY(callflags, fobp);
208 if (fobp->flags & FO_MOUNTTARGET)
209 return false; /* already mounted */
210 fobp->flags |= FDO_BUSY | FO_MOUNTTARGET |
211 (callflags & FO_DIRECTORY);
212 *bindpp = &fobp->bind;
213 return true;
214}
215/* unmounts the file object and frees it if now unusued */
216void fileobj_unmount(struct file_base_binding *bindp)
217{
218 struct fileobj_binding *fobp = (struct fileobj_binding *)bindp;
219 if (!(fobp->flags & FO_MOUNTTARGET))
220 return; /* not mounted */
221 if (STREAM_FIRST(fobp) == NULL)
222 release_binding(fobp); /* no longer in use */
223 else
224 fobp->flags &= ~FO_MOUNTTARGET;
225}
226
172/* opens the file object for a new stream and sets up the caches; 227/* opens the file object for a new stream and sets up the caches;
173 * the stream must already be opened at the FS driver level and *stream 228 * the stream must already be opened at the FS driver level and *stream
174 * initialized. 229 * initialized.
@@ -180,10 +235,13 @@ void fileobj_fileop_open(struct filestr_base *stream,
180 const struct file_base_info *srcinfop, 235 const struct file_base_info *srcinfop,
181 unsigned int callflags) 236 unsigned int callflags)
182{ 237{
238 /* assign base file information */
183 struct fileobj_binding *fobp; 239 struct fileobj_binding *fobp;
184 bool first = binding_assign(srcinfop, &fobp); 240 bind_source_info(srcinfop, &fobp);
241 unsigned int foflags = fobp->flags;
185 242
186 /* add stream to this file's list */ 243 /* add stream to this file's list */
244 bool first = STREAM_FIRST(fobp) == NULL;
187 ll_insert_last(&fobp->list, &stream->node); 245 ll_insert_last(&fobp->list, &stream->node);
188 246
189 /* initiate the new stream into the enclave */ 247 /* initiate the new stream into the enclave */
@@ -197,27 +255,16 @@ void fileobj_fileop_open(struct filestr_base *stream,
197 if (first) 255 if (first)
198 { 256 {
199 /* first stream for file */ 257 /* first stream for file */
200 fobp->bind.info = *srcinfop; 258 fobp->flags = foflags | FDO_BUSY | FO_SINGLE |
201 fobp->flags = FDO_BUSY | FO_SINGLE | 259 (callflags & (FO_DIRECTORY|FO_TRUNC));
202 (callflags & (FO_DIRECTORY|FO_TRUNC)); 260 fobp->writers = 0;
203 fobp->writers = 0; 261 fobp->size = 0;
204 fobp->size = 0;
205
206 fileobj_bind_file(&fobp->bind);
207 } 262 }
208 else 263 else
209 { 264 {
210 /* additional stream for file */ 265 /* additional stream for file */
211 fobp->flags &= ~FO_SINGLE; 266 fobp->flags = (foflags & ~FO_SINGLE) | (callflags & FO_TRUNC);
212 fobp->flags |= callflags & FO_TRUNC; 267 CHECK_FO_DIRECTORY(callflags, fobp);
213
214 /* once a file/directory, always a file/directory; such a change
215 is a bug */
216 if ((callflags ^ fobp->flags) & FO_DIRECTORY)
217 {
218 DEBUGF("%s - FO_DIRECTORY flag does not match: %p %u\n",
219 __func__, stream, callflags);
220 }
221 } 268 }
222 269
223 if ((callflags & FD_WRITE) && ++fobp->writers == 1) 270 if ((callflags & FD_WRITE) && ++fobp->writers == 1)
@@ -257,12 +304,14 @@ void fileobj_fileop_close(struct filestr_base *stream)
257 if (foflags & FO_SINGLE) 304 if (foflags & FO_SINGLE)
258 { 305 {
259 /* last stream for file; close everything */ 306 /* last stream for file; close everything */
260 fileobj_unbind_file(&fobp->bind);
261
262 if (fobp->writers) 307 if (fobp->writers)
263 file_cache_free(&fobp->cache); 308 file_cache_free(&fobp->cache);
264 309
265 binding_add_to_free_list(fobp); 310 /* binding must stay valid if something is mounted to here */
311 if (foflags & FO_MOUNTTARGET)
312 fobp->flags = foflags & (FDO_BUSY|FO_DIRECTORY|FO_MOUNTTARGET);
313 else
314 release_binding(fobp);
266 } 315 }
267 else 316 else
268 { 317 {