summaryrefslogtreecommitdiff
path: root/firmware/common/fileobj_mgr.c
diff options
context:
space:
mode:
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 {