diff options
Diffstat (limited to 'firmware/common/fileobj_mgr.c')
-rw-r--r-- | firmware/common/fileobj_mgr.c | 126 |
1 files changed, 66 insertions, 60 deletions
diff --git a/firmware/common/fileobj_mgr.c b/firmware/common/fileobj_mgr.c index 8e7831d36c..e34a460e10 100644 --- a/firmware/common/fileobj_mgr.c +++ b/firmware/common/fileobj_mgr.c | |||
@@ -187,7 +187,8 @@ void fileobj_fileop_open(struct filestr_base *stream, | |||
187 | ll_insert_last(&fobp->list, &stream->node); | 187 | ll_insert_last(&fobp->list, &stream->node); |
188 | 188 | ||
189 | /* initiate the new stream into the enclave */ | 189 | /* initiate the new stream into the enclave */ |
190 | stream->flags = FDO_BUSY | (callflags & (FD_WRITE|FD_WRONLY|FD_APPEND)); | 190 | stream->flags = FDO_BUSY | |
191 | (callflags & (FF_MASK|FD_WRITE|FD_WRONLY|FD_APPEND)); | ||
191 | stream->infop = &fobp->bind.info; | 192 | stream->infop = &fobp->bind.info; |
192 | stream->fatstr.fatfilep = &fobp->bind.info.fatfile; | 193 | stream->fatstr.fatfilep = &fobp->bind.info.fatfile; |
193 | stream->bindp = &fobp->bind; | 194 | stream->bindp = &fobp->bind; |
@@ -202,14 +203,6 @@ void fileobj_fileop_open(struct filestr_base *stream, | |||
202 | fobp->writers = 0; | 203 | fobp->writers = 0; |
203 | fobp->size = 0; | 204 | fobp->size = 0; |
204 | 205 | ||
205 | if (callflags & FD_WRITE) | ||
206 | { | ||
207 | /* first one is a writer */ | ||
208 | fobp->writers = 1; | ||
209 | file_cache_init(&fobp->cache); | ||
210 | filestr_assign_cache(stream, &fobp->cache); | ||
211 | } | ||
212 | |||
213 | fileobj_bind_file(&fobp->bind); | 206 | fileobj_bind_file(&fobp->bind); |
214 | } | 207 | } |
215 | else | 208 | else |
@@ -225,32 +218,33 @@ void fileobj_fileop_open(struct filestr_base *stream, | |||
225 | DEBUGF("%s - FO_DIRECTORY flag does not match: %p %u\n", | 218 | DEBUGF("%s - FO_DIRECTORY flag does not match: %p %u\n", |
226 | __func__, stream, callflags); | 219 | __func__, stream, callflags); |
227 | } | 220 | } |
221 | } | ||
228 | 222 | ||
229 | if (fobp->writers) | 223 | if ((callflags & FD_WRITE) && ++fobp->writers == 1) |
230 | { | 224 | { |
231 | /* already writers present */ | 225 | /* first writer */ |
232 | fobp->writers++; | 226 | file_cache_init(&fobp->cache); |
233 | filestr_assign_cache(stream, &fobp->cache); | 227 | FOR_EACH_STREAM(FIRST, fobp, s) |
234 | } | 228 | filestr_assign_cache(s, &fobp->cache); |
235 | else if (callflags & FD_WRITE) | 229 | } |
236 | { | 230 | else if (fobp->writers) |
237 | /* first writer */ | 231 | { |
238 | fobp->writers = 1; | 232 | /* already writers present */ |
239 | file_cache_init(&fobp->cache); | 233 | filestr_assign_cache(stream, &fobp->cache); |
240 | FOR_EACH_STREAM(FIRST, fobp, s) | 234 | } |
241 | filestr_assign_cache(s, &fobp->cache); | 235 | else |
242 | } | 236 | { |
243 | /* else another reader */ | 237 | /* another reader and no writers present */ |
238 | file_cache_reset(stream->cachep); | ||
244 | } | 239 | } |
245 | } | 240 | } |
246 | 241 | ||
247 | /* close the stream and free associated resources */ | 242 | /* close the stream and free associated resources */ |
248 | void fileobj_fileop_close(struct filestr_base *stream) | 243 | void fileobj_fileop_close(struct filestr_base *stream) |
249 | { | 244 | { |
250 | switch (stream->flags) | 245 | if (!(stream->flags & FDO_BUSY)) |
251 | { | 246 | { |
252 | case 0: /* not added to manager */ | 247 | /* not added to manager or forced-closed by unmounting */ |
253 | case FV_NONEXIST: /* forced-closed by unmounting */ | ||
254 | filestr_base_destroy(stream); | 248 | filestr_base_destroy(stream); |
255 | return; | 249 | return; |
256 | } | 250 | } |
@@ -260,30 +254,30 @@ void fileobj_fileop_close(struct filestr_base *stream) | |||
260 | 254 | ||
261 | ll_remove(&fobp->list, &stream->node); | 255 | ll_remove(&fobp->list, &stream->node); |
262 | 256 | ||
263 | if ((foflags & FO_SINGLE) || fobp->writers == 0) | 257 | if (foflags & FO_SINGLE) |
264 | { | 258 | { |
265 | if (foflags & FO_SINGLE) | 259 | /* last stream for file; close everything */ |
266 | { | 260 | fileobj_unbind_file(&fobp->bind); |
267 | /* last stream for file; close everything */ | ||
268 | fileobj_unbind_file(&fobp->bind); | ||
269 | 261 | ||
270 | if (fobp->writers) | 262 | if (fobp->writers) |
271 | file_cache_free(&fobp->cache); | 263 | file_cache_free(&fobp->cache); |
272 | 264 | ||
273 | binding_add_to_free_list(fobp); | 265 | binding_add_to_free_list(fobp); |
274 | } | ||
275 | } | 266 | } |
276 | else if ((stream->flags & FD_WRITE) && --fobp->writers == 0) | 267 | else |
277 | { | 268 | { |
278 | /* only readers remain; switch back to stream-local caching */ | 269 | if ((stream->flags & FD_WRITE) && --fobp->writers == 0) |
279 | FOR_EACH_STREAM(FIRST, fobp, s) | 270 | { |
280 | filestr_copy_cache(s, &fobp->cache); | 271 | /* only readers remain; switch back to stream-local caching */ |
272 | FOR_EACH_STREAM(FIRST, fobp, s) | ||
273 | filestr_copy_cache(s, &fobp->cache); | ||
281 | 274 | ||
282 | file_cache_free(&fobp->cache); | 275 | file_cache_free(&fobp->cache); |
283 | } | 276 | } |
284 | 277 | ||
285 | if (!(foflags & FO_SINGLE) && fobp->list.head == fobp->list.tail) | 278 | if (fobp->list.head == fobp->list.tail) |
286 | fobp->flags |= FO_SINGLE; /* only one open stream remaining */ | 279 | fobp->flags |= FO_SINGLE; /* only one open stream remaining */ |
280 | } | ||
287 | 281 | ||
288 | filestr_base_destroy(stream); | 282 | filestr_base_destroy(stream); |
289 | } | 283 | } |
@@ -320,15 +314,10 @@ void fileobj_fileop_rename(struct filestr_base *stream, | |||
320 | /* informs manager than directory entries have been updated */ | 314 | /* informs manager than directory entries have been updated */ |
321 | void fileobj_fileop_sync(struct filestr_base *stream) | 315 | void fileobj_fileop_sync(struct filestr_base *stream) |
322 | { | 316 | { |
323 | fileobj_sync_parent((const struct file_base_info *[]){ stream->infop }, 1); | 317 | if (((struct fileobj_binding *)stream->bindp)->flags & FO_REMOVED) |
324 | } | 318 | return; /* no dir to sync */ |
325 | 319 | ||
326 | /* inform manager that file has been truncated */ | 320 | fileobj_sync_parent((const struct file_base_info *[]){ stream->infop }, 1); |
327 | void fileobj_fileop_truncate(struct filestr_base *stream) | ||
328 | { | ||
329 | /* let caller update internal info */ | ||
330 | FOR_EACH_STREAM(FIRST, (struct fileobj_binding *)stream->bindp, s) | ||
331 | ftruncate_internal_callback(stream, s); | ||
332 | } | 321 | } |
333 | 322 | ||
334 | /* query for the pointer to the size storage for the file object */ | 323 | /* query for the pointer to the size storage for the file object */ |
@@ -340,6 +329,16 @@ file_size_t * fileobj_get_sizep(const struct filestr_base *stream) | |||
340 | return &((struct fileobj_binding *)stream->bindp)->size; | 329 | return &((struct fileobj_binding *)stream->bindp)->size; |
341 | } | 330 | } |
342 | 331 | ||
332 | /* iterate the list of streams for this stream's file */ | ||
333 | struct filestr_base * fileobj_get_next_stream(const struct filestr_base *stream, | ||
334 | const struct filestr_base *s) | ||
335 | { | ||
336 | if (!stream->bindp) | ||
337 | return NULL; | ||
338 | |||
339 | return s ? STREAM_NEXT(s) : STREAM_FIRST((struct fileobj_binding *)stream->bindp); | ||
340 | } | ||
341 | |||
343 | /* query manager bitflags for the file object */ | 342 | /* query manager bitflags for the file object */ |
344 | unsigned int fileobj_get_flags(const struct filestr_base *stream) | 343 | unsigned int fileobj_get_flags(const struct filestr_base *stream) |
345 | { | 344 | { |
@@ -349,20 +348,21 @@ unsigned int fileobj_get_flags(const struct filestr_base *stream) | |||
349 | return ((struct fileobj_binding *)stream->bindp)->flags; | 348 | return ((struct fileobj_binding *)stream->bindp)->flags; |
350 | } | 349 | } |
351 | 350 | ||
352 | /* change manager bitflags for the file object */ | 351 | /* change manager bitflags for the file object (permitted only) */ |
353 | void fileobj_change_flags(struct filestr_base *stream, | 352 | void fileobj_change_flags(struct filestr_base *stream, |
354 | unsigned int flags, unsigned int mask) | 353 | unsigned int flags, unsigned int mask) |
355 | { | 354 | { |
356 | struct fileobj_binding *fobp = (struct fileobj_binding *)stream->bindp; | 355 | struct fileobj_binding *fobp = (struct fileobj_binding *)stream->bindp; |
357 | if (fobp) | 356 | if (!fobp) |
358 | fobp->flags = (fobp->flags & ~mask) | (flags & mask); | 357 | return; |
358 | |||
359 | mask &= FDO_CHG_MASK; | ||
360 | fobp->flags = (fobp->flags & ~mask) | (flags & mask); | ||
359 | } | 361 | } |
360 | 362 | ||
361 | /* mark all open streams on a device as "nonexistant" */ | 363 | /* mark all open streams on a device as "nonexistant" */ |
362 | void fileobj_mgr_unmount(IF_MV_NONVOID(int volume)) | 364 | void fileobj_mgr_unmount(IF_MV_NONVOID(int volume)) |
363 | { | 365 | { |
364 | /* right now, there is nothing else to be freed when marking a descriptor | ||
365 | as "nonexistant" but a callback could be added if that changes */ | ||
366 | FOR_EACH_VOLUME(volume, v) | 366 | FOR_EACH_VOLUME(volume, v) |
367 | { | 367 | { |
368 | struct fileobj_binding *fobp; | 368 | struct fileobj_binding *fobp; |
@@ -371,11 +371,17 @@ void fileobj_mgr_unmount(IF_MV_NONVOID(int volume)) | |||
371 | struct filestr_base *s; | 371 | struct filestr_base *s; |
372 | while ((s = STREAM_FIRST(fobp))) | 372 | while ((s = STREAM_FIRST(fobp))) |
373 | { | 373 | { |
374 | /* last ditch effort to preserve FS integrity; we could still | ||
375 | be alive (soft unmount, maybe); we get informed early */ | ||
376 | fileop_onunmount_internal(s); | ||
377 | |||
378 | if (STREAM_FIRST(fobp) == s) | ||
379 | fileop_onclose_internal(s); /* above didn't close it */ | ||
380 | |||
374 | /* keep it "busy" to avoid races; any valid file/directory | 381 | /* keep it "busy" to avoid races; any valid file/directory |
375 | descriptor returned by an open call should always be | 382 | descriptor returned by an open call should always be |
376 | closed by whomever opened it (of course!) */ | 383 | closed by whoever opened it (of course!) */ |
377 | fileop_onclose_internal(s); | 384 | s->flags = (s->flags & ~FDO_BUSY) | FD_NONEXIST; |
378 | s->flags = FV_NONEXIST; | ||
379 | } | 385 | } |
380 | } | 386 | } |
381 | } | 387 | } |